Bukkit conversation fails sleeping - java

I'm trying to use a Bukkit conversation, which already works, yet, when I use TimeUnit.SECONDS.sleep(integer-value), it works once, and then it fails with this error in console: java.lang.InterruptedException: sleep interrupted
When a prompt has been shown and the next is going to be shown the method acceptInput is called. In the first prompt it works all fine, in the other prompts, which are called out of this prompt (the prompt calls a new instance of itself). All works fine except the sleep part. Any ideas to fix this?
Here is my code:
package dbx12.Test1.Tutorial.Prompts;
import java.util.concurrent.TimeUnit;
import org.bukkit.conversations.ConversationContext;
import org.bukkit.conversations.Prompt;
import org.bukkit.entity.Player;
public class Text implements Prompt {
#Override
public Prompt acceptInput(ConversationContext context, String input) {
int thisPrompt = (int) context.getSessionData("step");
context.setSessionData("step", thisPrompt+1);
Player p = (Player) context.getForWhom();
boolean type;
try {
TimeUnit.SECONDS.sleep(dbx12.Test1.Utils.Prompt_List.delay.get(thisPrompt));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace(); //DEBUG
}
try {
type = dbx12.Test1.Utils.Prompt_List.promptType.get(thisPrompt+1);
} catch (Exception e) {
return new Finish();
}
if(dbx12.Test1.Utils.Prompt_List.hasLocation.get(thisPrompt+1) == true)
p.teleport(dbx12.Test1.Utils.Prompt_List.location.get(thisPrompt+1));
if(type==true)
{
System.out.println("return a text");
return new Text();
}
else
{
System.out.println("return a interaction");
return new Interaction();
}
}
#Override
public boolean blocksForInput(ConversationContext context) {
return false;
}
#Override
public String getPromptText(ConversationContext context) {
return dbx12.Test1.Utils.Prompt_List.promptText.get(context.getSessionData("step"));
}
}

sleep will cause your entire server to stop doing anything for x seconds. Instead of sleep, use a SyncDelayedTask:
this.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable(){
public void run(){
//what you want to do here
}
},delayInSeconds * 20);
so, lets say for example you wanted to send test1 to the server, then test2 to the server 5 seconds later, you could use:
int repeats;
public void sendMessages(){
this.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable(){
public void run(){
if(repeats == 0){ //if it's the first time running
Bukkit.getServer.broadcastMessage("test1");
repeats++; //add to repeats
sendMessages(); //call the method again
}
else if(repeats == 1){ //if it is the second time being called
Bukkit.getServer.broadcastMessage("test2");
}
}
},5 * 20);//wait 5 seconds
so with the above code, you could make a method like this:
public void startSendingMessages(){
repeats = 0;
sendMessages();
}
Where when you called startSendingMessages(), the test1 would be sent, then, 5 seconds later, test2 would be sent.
The reason we are multiplying the time in seconds by 20, is because it has to be in ticks, or minecraft time, and 1 second = 20 ticks.
There's lots of other scheduler types, like SyncRepeatingTasks. To learn more about them, check out the bukkit JavaDocs: http://jd.bukkit.org/dev/apidocs/, theres also a nice tutorial from bukkit here: http://wiki.bukkit.org/Scheduler_Programming

Related

How to count incoming messages from a "stream" in Java?

So I'm receiving numerous messages from a stream - well, it's not a stream per se, it's really a method that's fired off when a message is received - and I would like to count the number of messages received in 10 seconds.
Here's what I have so far:
package com.example.demo;
import java.net.URI;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
public class ExampleClient extends WebSocketClient {
private float messagesRecievedCount;
public ExampleClient(URI serverUri) {
super(serverUri);
System.out.println("Created object");
setMessagesRecievedCount(0);
}
#Override
public void onOpen(ServerHandshake serverHandshake) {
System.out.println("Connection established!");
}
#Override
public void onMessage(String s) {
setMessagesRecievedCount(getMessagesRecievedCount() + 1);
}
public void getMessagesPerMinute(){
float start = getMessagesRecievedCount();
float end = 0;
long ten = System.currentTimeMillis() + 1000;
while(System.currentTimeMillis() < ten) {
end = getMessagesRecievedCount();
}
System.out.println("start: "+start+" end: "+end+
"Total messages: "+ (end-start)+"\n");
}
public float getMessagesRecievedCount() {
return messagesRecievedCount;
}
public void setMessagesRecievedCount(float messagesRecievedCount) {
this.messagesRecievedCount = messagesRecievedCount;
}
}
I have a global variable messagesRecievedCount which keeps a running count of messages received from a websocket stream. Whenever a message is received the onMessage() method is fired and it updates the message count. I want to count the number of messages received in 10 seconds (and extrapolate it to a minute) - for which I have the getMessagesPerMinute().
Obviously the way I'm doing it is not smart - it's blocking and the count of messages after 10 seconds is the same (when actually it isn't, I've actually received 20 messages). I feel like I should be doing threads but I don't know how to go about it. What would you suggest? I'm really new to this and just tinkering around.
This is the main class where I'm calling ExampleClient.java from:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.web.socket.WebSocketSession;
import java.net.URI;
import java.net.URISyntaxException;
#SpringBootApplication
public class DemoApplication {
private WebSocketSession clientSession;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
public DemoApplication () throws URISyntaxException {
ExampleClient c = new ExampleClient( new URI( "wss://example.com/" ) );
c.connect();
c.getMessagesPerMinute();
}
}
The c.connect() establishes the connection and the onMessage() is triggered soon after!
Your code actully runs fo 1 second (1000ms, I don't know if this is a typo or a voluntary simplification). One other problem is that it calls end = getMessagesRecievedCount(); repeatedly inside a while loop, while you actually need only the starting and final value. A way to solve this would be using Thread.sleep() (if you never need to cancel the counting midway):
public void getMessagesPerMinute(){
float start = getMessagesRecievedCount();
float end = 0;
try{
Thread.sleep(10000);
}
catch(InterruptedException e){
System.out.println("do something");
}
end = getMessagesRecievedCount();
System.out.println("start: "+start+" end: "+end+
"Total messages: "+ (end-start)+"\n");
}
For blocking the important thing is that this code runs in a different thread that the one updating the value of messagesRecievedCount or doing other things that you may want to do in the meanwhile, so calling it inside a new thread is probably the best solution. I'm not familiar with the framework you are using so it may be already using different threads that better suit this purpose.
If you intend to do something more with the variable messagesRecievedCount some synchronization would be required, but for an estimate of the number of messages for minute this should be good enough.
Here is some test code I used that you can hopefully adapt to better suit your case and play with to pinpoint the problem. The difference is quite constant in this case, but the values are clearly updated. Making the ExampleClient instance public is a shortcut which should probaby be avoided in the actual code.
public class Test{
public static ExampleClient example=new ExampleClient();
public static void main(String[] args){
Thread a=new MessagesPerTenSecondFetcher();
Thread b=new MessagesPerTenSecondFetcher();
Thread c=new MessagesPerTenSecondFetcher();
Thread d= new MessageProducer();
a.start();
d.start();
b.start();
try{
Thread.sleep(2000);
}
catch(InterruptedException e){
System.out.println("do something");
}
c.start();
}
}
class ExampleClient {
private float messagesRecievedCount;
public void onMessage(String s) {
setMessagesRecievedCount(getMessagesRecievedCount() + 1);
}
public void getMessagesPerMinute(){
float start = getMessagesRecievedCount();
float end = 0;
try{
Thread.sleep(10000);
}
catch(InterruptedException e){
System.out.println("do something");
}
end = getMessagesRecievedCount();
System.out.println("start: "+start+" end: "+end+
"Total messages: "+ (end-start)+"\n");
}
public float getMessagesRecievedCount() {
return messagesRecievedCount;
}
public void setMessagesRecievedCount(float messagesRecievedCount) {
this.messagesRecievedCount = messagesRecievedCount;
}
}
class MessagesPerTenSecondFetcher extends Thread{
#Override
public void run(){
Test.example.getMessagesPerMinute();
}
}
class MessageProducer extends Thread{
#Override
public void run(){
for(int i =0; i<100;i++){
Test.example.onMessage("a");
try{
Thread.sleep(130);
}
catch(InterruptedException e){
System.out.println("do something");
}
}
}
}

Java: two threads printing & receiving user input via Scanner: program doesn't exit after exception is thrown

I have this program with two threads: lessonThread and questionThread. The lesson thread prints Lesson continues, while the question thread every 5 seconds asks Finish lesson? and asks a user for input via Scanner. I have a wait() call in questionThread that throws an exception. In the catch block I use System.exit() to terminate the program, however it doesn't work right away - only after many lesson messages. At the same time, if I go through breakpoints in both thread in a debugger, it System.exit() terminates the program very soon.
public class LessonNotify {
private volatile boolean finished;
private Scanner scanner = new Scanner(System.in);
private Thread lessonThread;
private Thread questionThread;
public static void main(String[] args) {
LessonNotify lesson = new LessonNotify();
lesson.lessonThread = lesson.new LessonThread();
lesson.questionThread = lesson.new QuestionThread();
lesson.lessonThread.start();
lesson.questionThread.start();
}
class LessonThread extends Thread {
#Override
public void run() {
while (!finished) {
System.out.println("Lesson continues");
}
}
}
class QuestionThread extends Thread {
private Instant sleepStart = Instant.now();
#Override
public void run() {
while (!finished) {
if (Instant.now().getEpochSecond() - sleepStart.getEpochSecond() >= 5) {
try {
lessonThread.wait();
} catch (Exception e) {
e.printStackTrace();
finished = true;
System.exit(0);
}
System.out.print("Finish a lesson? y/n");
String reply = scanner.nextLine().substring(0, 1);
switch (reply.toLowerCase()) {
case "y":
finished = true;
}
sleepStart = Instant.now();
lessonThread.notify();
}
}
}
}
}
That's just how exiting works. The messages printed by the other thread, especially because it has no breaks on the car, are already in various buffers. By using a debugger the thread is frozen or at least runs slower, thus, you don't observe it.
See my other answer. When I said 'this is not how you thread' - there are a billion reasons why, and this is one of the billion.

GUI Takes Longer Than Calculation And Slows Entire Process

We have a complex calculation that takes a variable time. With some input values thousand steps can be done in one second - with other input values a step takes several seconds.
That's completely correct, so we just want to inform the user about the progress. The problem is that in the former case updating the GUI takes longer than the actual calculation, so after it is done there are still about 10 seconds of GUI update events in the queue (which in that case triples the execution time of the entire calculation).
I think that's a general problem, so I broke it down to a somewhat framework agnostic example:
public class QueueTest {
static final int STEPS = 30;
public static void main(String[] args) {
final Gui gui = // ...
final Display display = Display.getDefault();
final Thread thread = new Thread(() -> {
for (int i = 0; i < STEPS; i++) {
final int step = i; // calculate something etc.
gui.updateLater(display, step);
}
System.out.println("Finished calculation.");
});
thread.start();
while (true) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
interface Gui {
default void updateLater(Display display, int step) {
display.asyncExec(() -> update(step));
}
default void update(int step) {
System.out.println("Update " + (step + 1) + " / " + STEPS);
if (step == STEPS - 1) {
System.out.println("Finished GUI.");
}
}
}
}
(The additional Thread only "calculates" steps and sends it to the GUI to show the progress.)
So let's consider some implementations of Gui:
static class NoGui implements Gui {
#Override
public void update(int step) {
if (step == STEPS - 1) {
System.out.println("Finished GUI.");
}
}
}
This example prints only when the GUI is finished. The result is these two lines, printed at almost the same time:
Finished calculation.
Finished GUI.
That's perfectly reasonable. The GUI events are quick to be finished. Now let's make them slow:
static class SlowGui implements Gui {
#Override
public void update(int step) {
try {
Thread.sleep(100);
Gui.super.update(step);
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
This prints something like the following, with the finishing of calculation and the GUI three seconds apart:
Finished calculation.
Update 1 / 30
Update 2 / 30
Update 3 / 30
...
Update 30 / 30
Finished GUI.
That's what I'm seeing in our application. The calculation finishes, but the GUI is too slow and has to execute its event queue after the calculation is already done.
I want to optimize this behavior and came up with something like this:
static class IgnorantGui extends SlowGui {
private boolean inProgress;
private Integer nextStep;
#Override
public void updateLater(Display display, int step) {
if (this.inProgress) {
this.nextStep = Integer.valueOf(step);
} else {
this.inProgress = true;
super.updateLater(display, step);
}
}
#Override
public void update(int step) {
try {
Integer currentStep = Integer.valueOf(step);
do {
super.update(currentStep.intValue());
currentStep = this.nextStep;
this.nextStep = null;
} while (currentStep != null);
} finally {
this.inProgress = false;
}
}
}
The output is the following four lines:
Finished calculation.
Update 1 / 30
Update 30 / 30
Finished GUI.
This implementation just ignores the events in between and so is a lot quicker. This is a valid solution to my problem.
I think this entire use case might be common, and maybe there is a more elegant solution. Or even some standard Java API to handle it. (Maybe some SWT / Eclipse Framework API, since that's what we're using.)
So... how to handle a GUI that takes longer to update than the calculation and so slows the application down?
One way that I use is to poll the background thread using a timer runnable in the UI thread. Use Display.timerExec for this:
display.timerExec(100, new Runnable() {
#Override
public void run() {
// TODO update UI from background thread details
// Run again
display.timerExec(100, this);
}
});
The background thread doesn't do any asyncExec calls it just maintains data that the UI thread can access.
don't know if I get it right but it seems that you are continuously updating the GUI. Try to add something like a counter that determines when the gui should be updated. Or if it isnt needed to see all steps try something like
static class SlowGui implements Gui {
#Override
public void update(int step) {
try {
if(step%5==0){
Gui.super.update(step);
}
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
this should update every 5 steps.
And why is there a sleep in the update method?
Hope I could help you.

Not able to end the workflow when thread stops

I am just not able to figure out the cause of this issue.
Problem :
1) I am using a Thread.Sleep function to set the timer for my application.
2) Now as soon as user enter the webPage the timer starts, if user clicks any link the timer(thread) is stopped and then new timer starts.
3) If their is no activity for say 3 seconds, timer ends and with it workflow associated with the webpage ends too.
Code :
DownloadSummariesPage.java
public DownloadSummariesPage(){
abc = new SimpleThread(this);
Link<Void> link = new Link<Void>("downloadSummaryLink") {
public void onClick() {
boolean threadStatus = abc.checkStatus();
if (threadStatus) {
abc.interrupt();
abc.stop();
abc = new SimpleThread(DownloadSummariesPage.this);
abc.start();
}
else
{
LOG.debug("thread is dead now");
endWorkflow();
LOG.debug("ending the workflow");
setResponsePage(MenuPage.class);
}
}
};
abc.start();
}
public void endWorkflow() {
abc.interrupt();
abc.stop();
boolean downloadReport = false;
LOG.debug("before action 201 inside endworkflow");
Map<String, Serializable> inputs = new HashMap<String, Serializable>();
inputs.put("downloadReport", downloadReport);
try {
wf.doAction(id, 201, inputs);//do not worry about this its for workflow
String empty = "";
populateDownloadReportDatabase(empty);
setResponsePage(MenuPage.class);
} catch (Exception e) {
LOG.debug("Exception while performing 201 workflow, getControlCancel "
+ e);
}
}
}
My next class which creates thread is
SimpleThread.java
class SimpleThread extends Thread {
private static final Logger LOG = Logger.getLogger(SimpleThread.class);
boolean stillActive = true;
DownloadSummariesPage dsp;
SimpleThread(DownloadSummariesPage dp) {
this.dsp = dp;
}
public void run() {
// 5sec timer
LOG.debug("inside run method");
try {
Thread.sleep(3000);
stillActive = false;
} catch (InterruptedException e) {
LOG.debug("Exception in thread " + e);
e.printStackTrace();
}
LOG.debug("before endworkflow");
dsp.endWorkflow();//so this is what i actually want to do...
LOG.debug("at the end of simplethread");
}
public boolean checkStatus() {
return stillActive;
}
}
Cases :
1) Whats Happening : User logs in thread sleeps, user click a link thread stops and creates a new one if user again click it happens again and now if user do not do anything for 3 seconds, stillAlive variable in SimpleThread class is set to false and when now user click its ends the workflow perfectly...
2) What i want : if user logs in thread starts, and if their is no activity by the user stillAlive variable is set to false and dsp.endWorkflow(); statement now should end the workflow. right ? but it just stops after reaching inside the endWorkflow() function and do not actually end the workflow...
Hope you get this, I tried my best to make it understandable. Thanks for your time..
I appreciate any help..
So there are some strange things here.
first assume the thread sleep without any interruption for 3 sec, so it will call the dsp.endWorkflow() where you call it again from the onClick method.
second the stillAlive flag should be volatile
boolean volatile stillActive = true;
The possible error/bug would raises by this section.
if (threadStatus) {
abc.interrupt();
abc.stop();// you cannot get to this like just after interrupt, maybe thread abc goes first
abc = new SimpleThread(DownloadSummariesPage.this);
abc.start();
}
because assume when thread is sleeping you interrupt it, then stop it, but this is possible that thread finishes it's work just after you interrupt it (before you stop it). so this is better to just stop it, or return when thread reached the catch.
try {
Thread.sleep(3000);
stillActive = false;
} catch (InterruptedException e) {
LOG.debug("Exception in thread " + e);
e.printStackTrace();
return;//////give up the rest work. so you don't need to call the stop too.
}
And the error is here
assume that user don't click the cancel, or new download, and thread just finishes its sleeping and call the dsp.endWorkflow(), so what is going on this method?
public void endWorkflow() {
abc.interrupt();
abc.stop();//error here!
boolean downloadReport = false;//this is unreachable
}
Just look, you are calling this method by abc thread, and the error is that you are killing the thread just inside the method, before you set the downloadReport to false. so it may would be like this.
public void endWorkflow() {
boolean downloadReport = false;//this is unreachable
abc.interrupt();
abc.stop();//error here!
}
I hope I could some help.

java wait() statement after catch clause

When I run the program it does not display "HIIII."
I am a novice (sort of) so please dont "hate".
Is my wait() statement wrong? Or what am I doing wrong?
Is it the ArrayIndexOutOfBounds catch clause? Please help!
[edit] oh so is it the main method?? that it doesnt do anything?
[edit] i know the wait and notify is wrong... please don't mention it.
//this is the whole class
import javax.swing.*;
import javax.swing.JOptionPane;
public class none {
static boolean game;
final static boolean on = true;
final static boolean off = false;
static boolean cheatMode;
public static void main(String[] args) {
game = on;
boolean tru = true;
try{
if(tru = Boolean.parseBoolean(args[0])){
cheatMode = on;
System.out.println("Cheats are on.");
}
}
catch(java.lang.ArrayIndexOutOfBoundsException e){
e.printStackTrace();
System.out.println("Ignore this error, it's from not running it on the command prompt.");
}
}
public class console extends Thread{
public void run(){
try{
wait();
JOptionPane.showMessageDialog(null,"HIIII");
}
catch(Exception e){
e.printStackTrace();
System.out.println("The console glitched...");
}
//hiiii
JOptionPane.showMessageDialog(null,"HIIII");
}
public class mainThingy extends Thread{
public void run() {
if(game = on)
notify();
}
}
}
}
There seems to be couple of issues
1) if(tru = Boolean.parseBoolean(args[0])){
Above statement is assignemt and not comparison. Use == operator.
2) Wait and notify should always be called from inside Synchronized blocks. Your code doesn't seem to be doing that.
I'd advise against the standard wait()-notify() structures. There are way better methods for this: the Java concurrency package.
Tutorial for Java Concurrency
API JavaDoc
JCIP, or Java Concurrency In Practice (Peierls, Bloch, Bowbeer, Holmes, Lea)
And as you seem to be in your first steps in learning Java, I'd suggest another two books:
Effective Java (Bloch)
Java puzzlers (Bloch, Gafter)
>java none true will print only Cheats are on. But your question is about printing Hiii. Isn't it ? You have got that in JOptionPane dialog inside the console class. Without initializing it how can you expect your program to print Hiii?. Also why have you written two public classes in one file ? When you are calling wait and nottify methods, you are also missing the synchronized statement. So when you start your threads console and mainThingy those will throw IllegalMonitorStateException anyways. So actually what are you trying to do ?
You main method doesn't actually start anything
wait and notify must be synchronized on the same monitor/lock
Your two threads are not sharing the same monitor/lock
if (game = on) in mainThingy is an assignment, not a check, it should be if (game == on)
UPDATE with Example
public class TestThread {
static boolean game;
final static boolean on = true;
final static boolean off = false;
static boolean cheatMode;
public static void main(String[] args) {
game = on;
boolean tru = true;
try {
if (args.length > 0) {
if (tru = Boolean.parseBoolean(args[0])) {
cheatMode = on;
System.out.println("Cheats are on.");
}
}
} catch (java.lang.ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
System.out.println("Ignore this error, it's from not running it on the command prompt.");
}
Console con = new Console();
con.start();
// Give time for the console thread to get started
do {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(TestThread.class.getName()).log(Level.SEVERE, null, ex);
}
} while (!con.isAlive());
System.out.println("Start main...");
Console.MainThingy main = new Console.MainThingy();
main.start();
}
public static class Console extends Thread {
// A shared lock that our two threads can communicate on...
public static final Object WAIT_LOCK = new Object();
public void run() {
try {
System.out.println("Waiting...");
// Must "own" the monitor before we can call wait
synchronized (WAIT_LOCK) {
WAIT_LOCK.wait();
}
JOptionPane.showMessageDialog(null, "HIIII");
} catch (Exception e) {
e.printStackTrace();
System.out.println("The console glitched...");
}
}
public static class MainThingy extends Thread {
public void run() {
if (game == on) {
// Must "own" the monitor before we can call notify
synchronized (WAIT_LOCK) {
System.out.println("Notify...");
WAIT_LOCK.notify();
}
}
}
}
}
}
Java Concurrency is fun, but it will bite you if you're not careful with it and treat it nicely.
Take a read through Currency in Java

Categories

Resources