Workaround to using the Bukkit API from separate thread

Discussion in 'Plugin Development' started by wreed12345, Sep 11, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    wreed12345

    Hey guys! I began using some multi threaded bukkit plugins, and I have a question about this. I noticed we are not supposed to access any part of the bukkit API while on this separate thread. I was hoping someone could explain why it would be dangerous to access the Chat api (specifically sending messages to the server) while not on the main server thread. Also instead of sending messages from the main thread would I be able to add the messages to an arraylist from the seperate thread, and then send them from the arraylist on the main thread? Would that be a valid workaround? Thanks!
     
  2. Offline

    1Rogue

    Using Callables would probably be a safer way to do it. You can see an example of my own implementation below.

    You can use the callable via:
    Bukkit.getScheduler().callSyncMethod(pluginInstance, new SendMessageCallable(player, message));

    where:
    player = (String) player name
    message = (String) message to send
    pluginInstance = (Plugin) the instance of your main plugin class

    SendMessageCallable:
    Code:java
    1. /**
    2.  *
    3.  * @since 1.4.0
    4.  * @author 1Rogue
    5.  * @version 1.4.0
    6.  */
    7. public class SendMessageCallable implements Callable {
    8.  
    9. private final String player;
    10. private final String message;
    11.  
    12. public SendMessageCallable(String playername, String messagetext) {
    13. player = playername;
    14. message = messagetext;
    15. }
    16.  
    17. public Object call() {
    18. Bukkit.getPlayer(player).sendMessage(_(message));
    19. return null;
    20. }
    21. }
    22.  

    The callable used:
    https://github.com/1Rogue/PlayTime/...ue/playtime/callable/SendMessageCallable.java
     
    wreed12345 likes this.
  3. Offline

    Janmm14

    You can do this, but then create the list with Collections.synchronizedList()
    You should have a synchronized bukkit task checking the list every tick, sending its content and removing the sent entry in the same for loop.
     
    wreed12345 likes this.
  4. Offline

    wreed12345

    1Rogue Janmm14 Which of the two seem better? I would probably go with the list since that is what I am familiar with but then again the callables allows me to do this from the other thread... They both seem good.
     
    Janmm14 likes this.
  5. Offline

    Janmm14

    The callable thing seems to just do something if it needs to be done while my thread-safe list needs to be checked every tick.
     
  6. Offline

    tommycake50

    Janmm14 What is the difference between a synchronized list and having your own list that has the volatile modifier?
     
  7. Offline

    Janmm14

  8. Offline

    tommycake50

  9. Offline

    hatstand

    You don't need a callable, since you aren't using extra functionality provided by it (The Future<T> returned by callSyncMethod). Use a Runnable and runTask() instead, it still executes on the main thread, according to my tests.
     
  10. Offline

    Janmm14

    I don't know.
     
  11. Offline

    Tirelessly

  12. Offline

    wacossusca34


    Don't use the volatile keyword if you don't know what it does.

    http://stackoverflow.com/questions/106591/do-you-ever-use-the-volatile-keyword-in-java and particularly the article referenced in this post here is relevant: https://www.ibm.com/developerworks/java/library/j-jtp06197/

    I seldom use the volatile keyword because the cost between using lock and volatile variables is usually irrelevant to bukkit plugins. There's no processor heavy loops in most plugins that exist in their own threads...

    It's safer to use synchronization because volatile fields only apply to certain situations.
     
    tommycake50 likes this.
  13. Offline

    Technius

    Synchronized lists (such as CopyOnWriteArrayList) are much, much slower than normal lists.
     
  14. Offline

    dillyg10

    You guys might be complicating this a bit...

    Bukkit.getSchedueler().runTask(Plugin, Runnable);

    NOW, if you are getting concurrent exceptions in your code from lists you have created... uhh, well... try using java.util.Vector, volatile modifier can work as well.... but yeah.

    Also, don't be scared to use Bukkit API in async thread, honestly you can do everything buy world/entity modification. Anything that has to do with getting information is safe to use in async thread :D.
     
Thread Status:
Not open for further replies.

Share This Page