I'm calling interrupt on day 370, and then calling it again during the catch block during the run method of the other classes. I also have a while condition that loops while thread is not interrupted, but for some reason, it's not working, and I have no idea why. I know I can use variable flag instead, but I want to try making interrupt() works. I've look at multiple sites already, but none seems to work for me. Please help.
public class Elf implements Runnable {
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// wait a day
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
public class Main {
public static void main(String args[]) {
Scenario scenario = new Scenario();
// create the participants
// Santa
scenario.setSanta( new Santa(scenario) );
Thread th = new Thread(scenario.getSanta());
th.start();
// The elves: in this case: 10
for (int i = 0; i != 10; i++) {
Elf elf = new Elf(i + 1, scenario);
scenario.getElves().add(elf);
th = new Thread(elf);
th.start();
}
// The reindeer: in this case: 9
for (int i = 0; i != 9; i++) {
Reindeer reindeer = new Reindeer(i + 1, scenario);
scenario.getReindeers().add(reindeer);
th = new Thread(reindeer);
th.start();
}
// now, start the passing of time
for (int day = 1; day < 500; day++) {
// wait a day
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// turn on December
if (day > (365 - 31)) {
scenario.setDecember(true);
}
// interrupt flag is set here
if (day == 370) {
th.interrupt();
}
// print out the state:
System.out.println("*********** Day " + day
+ " *************************");
scenario.getSanta().report();
for (Elf elf : scenario.getElves()) {
elf.report();
}
for (Reindeer reindeer : scenario.getReindeers()) {
reindeer.report();
}
}
}
}
I've only included the Elf class here, but the other classes are of the same structure with almost the same code in it. Right now the program finishes with the red square (terminate button) still lit, and I read that that is an indication that there are still threads running. I'm not sure why it's not stopping.
A variable declared as Thread th is a reference to an object of type Thread. It's only a reference to one object. This is true, by the way, for all types, not just thread.
Whenever you put a new value into a variable, it no longer refers to the old value[1].
Thus th.interrupt() in your code will just interrupt the last thread that you assigned to it - the most recent reindeer thread.
If you want to interrupt all the threads, you'll need to keep a reference to all the threads.
A basic solution
A simple way to do this would be to use a list of Thread:
List<Thread> allThreadsToInterrupt = new ArrayList<>();
When you create a thread, you do
th = new Thread(...);
allThreadsToInterrupt.add(th);
And then at the end you can do:
for ( Thread th: allThreadsToInterrupt ) {
th.interrupt();
}
Using a ThreadGroup
But in fact, Java has an existing class that helps you with this - the ThreadGroup class. You can do something like:
ThreadGroup elfThreads = new ThreadGroup("Elf Threads");
ThreadGroup reindeerThreads = new ThreadGroup( "Reindeer Threads" );
Now, whenever you create a thread, you should create it with a thread group:
Instead of:
th = new Thread(elf);
Use:
th = new Thread(elfThreads,elf);
Then at the end, to interrupt all the elves, you can run:
elfThreads.interrupt();
This would automatically call interrupt() on all threads that belong to the group.
Of course, you can just create one big group, but I demonstrated separating the elves and the reindeer, in case you will need them to be interrupted separately.
[1] In most cases replacing an old reference, which was the only reference to an object, with a new reference will cause the old object to be eligible for garbage collection, but threads are a little different, because if they have been started, there is a second reference to them from the current thread group (because that's the default when you don't give a thread group when you create a thread), which means that they will not be garbage-collected and they will run properly until they complete.
Related
I'm programming a little Java program where I need to create threads (philosophers in my code), and these philosophers need to change of state between thinking, hungry and eating.
I'm not that far into the project and I have the next problem:
public class NewMain {
static Philosopher [] p;
public static void main(String[] args) {
p = new Philosopher[5];
p[0] = new Philosopher(0);
p[1] = new Philosopher(1);
p[2] = new Philosopher(2);
p[3] = new Philosopher(3);
p[4] = new Philosopher(4);
for (int i = 0; i<5; i++) {
try{
p[i].run();
if(i == 4) {
p.notifyAll();
}
}
catch(IllegalMonitorStateException e) {}
}
}
}
I'm creating 5 philosophers(threads). Each one of those has a wait() instruction in their code:
#Override
public void run() {
int rand;
if (status == 0) {
System.out.println("Philosopher " + id + " is waiting.");
try {
wait();
System.out.println("Awoken");
while(status == 0) {
System.out.println("Philosopher " + id + " is thinking.");
sleep(100);
rand = ThreadLocalRandom.current().nextInt(0,100);
if(rand > 95){
status = 1;
System.out.println("Philosopher " + id + " changed state to hungry.");
}
}
}
catch(InterruptedException e) {
System.out.println("Error!");
}
catch(IllegalMonitorStateException e) {}
}
}
The problem is that when invoking notifyAll(), the processes don't awake and they just die after executing the run() method of each thread.
If anyone is wondering, I'm not using synchronized because I need to run the methods at the same time.
Also, I've tried to put notifyAll() inside the run() method of the threads.
Can anyone tell me what's going on and why are the threads not continuing
with their code?
Problems
notify[All]() and wait() should be used on the same instance. You are notifying on the array Philosopher[] p, but waiting on this which is a Philosopher. It's like I am waiting for you, but you are notifying Sarah that you're going to be late.
You have created the threads but haven't started them properly. Calling run will execute the method in the current thread. Use the method start instead. It begins execution concurrently.
To use x.notify[All]() or x.wait(), you have to be within a synchronised block synchronized(x) { ... }. Ignoring IllegalMonitorStateException won't help you at all.
Answers
... why are the threads not continuing with their code?
They might call wait after the 4th thread notifies them.
... the processes don't awake and they just die ...
They don't die, they still wait until you terminate the program.
I'm not using synchronizedbecause I need to run the methods at the same time
You need to run the methods at the same time correctly, right? Here, synchronisation is required at least for building wait-notify communication.
p is an array of Runnable. when you write
p[i].run();
Then, you are invoking run method (actually you haven't started a thread here instead called run method) using object stored at p[i] location. Now, as per notifyAll
Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the wait methods.
You should have used start() instead run() to start a new thread.
notify() and notifyAll are used when thread(s) are waiting to acquire monitor on current object.
I've been having trouble trying to get a waited thread to by notified.
Here is the code for where the notify() is called:
public static void main(String[] args)
{
int endUsers = 0;
Terminal terminal = new Terminal("Master");
ArrayList<Thread> threads = new ArrayList<Thread>();
threads.add(new Thread(
new EndUser("EndUser 1", DEFAULT_DST_NODE, 50000, 50001),
"EndUser 1"));
endUsers++;
threads.add(new Thread(
new EndUser("EndUser 2", DEFAULT_DST_NODE, 50001, 50000),
"EndUser 2"));
endUsers++;
for (Thread t : threads)
{
t.start();
}
while (true)
{
int user = terminal.readInt("Which user is sending data? ");
if (user <= endUsers && user > 0)
{
synchronized (threads.get(user - 1))
{
threads.get(user - 1).notify();
}
}
}
}
}
And here is the code where wait() is called:
public void run()
{
while (true)
{
try
{
synchronized (this)
{
this.wait();
}
this.send();
}
catch (Exception e)
{
}
}
}
I've tried everything I can think of but I have no idea why it isn't working.
threads.get(user - 1).notify();
is invoking notify on the Thread object, where
this.wait();
is waiting on your runnable, or the class in which the call is housed.
Using
Thread.currentThread().wait();
should fix your issue.
In addition, I would like to mention that creating an Object reference, then waiting on and notifying that would be a fully functional method to obtain what you want as well
You would create the Object as a(n) (optionally static) reference in your thread class
public final (static) Object waitObject = new Object();
Edit: ^ Making this final prevents other (likely malicious) code parts
from reassigning the value, which would make it so that the waitObject.notify()
method is never actually able to be reached.
Then use
waitObject.wait(); //or
waitObject.wait(time);
And
waitObject.notify(); //or
waitObject.notifyAll();
Edit:
As was pointed out by #shmosel, it is inherently unsafe to use "wait", "sleep", or "notify" from within a thread, as outlined within the Java Documentation. However, despite this, the functionality is still available for use, though discouraged.
For additional Java references you have multiple resources available to you; such as.:
Java API Overview, Java Thread API, This Google Search - Safe Java Practices (to which you can append what you are looking into, such as "Threading, Wait" for a search query of "Safe Java Practices Threading, Wait"), and many more.
I am new to concurrent programming and I am facing few issues with the below code using Java threads.
Status Class (this class tracks the position availability):
public class Status {
private static Map<String, Boolean> positions = new HashMap<>();
static {
//Initially all positions are free (so set to true)
positions.put("A", true);
positions.put("B", true);
}
public synchronized void occupyOrClear(String position,
boolean status) {
positions.put(position, status);
}
public boolean isClear(String position) {
return positions.get(position);
}
}
MyThread Class:
public class MyThread implements Runnable {
private String[] positions;
private String customer;
public MyThread(String customer, String[] positions) {
this.positions = positions;
this.customer = customer;
}
private Status status = new Status();
public void run() {
for (int i = 0; i < positions.length;) {
String position = positions[i];
if (status.isClear(position)) {
// position occupied now
status.occupyOrClear(position, false);
System.out.println(position + " occupied by :"+customer);
try {
//my real application logic goes below (instead of sleep)
Thread.sleep(2000);
} catch (InterruptedException inteExe) {
System.out.println(" Thread interrupted ");
}
// Now clear the position
status.occupyOrClear(position, true);
System.out.println(position + " finished & cleared by:"+customer);
i++;
} else {
try {
Thread.sleep(1000);
} catch (InterruptedException inteExe) {
System.out.println(" Thread interrupted ");
}
}
}
}
}
ThreadTest Class:
public class ThreadTest {
public static void main(String[] args) {
String[] positions = { "A", "B"};
Status status = new Status();
Thread customerThread1 = new Thread(new MyThread(status, "customer1", positions));
Thread customerThread2 = new Thread(new MyThread(status, "customer2", positions));
Thread customerThread3 = new Thread(new MyThread(status, "customer3", positions));
customerThread1.start();
customerThread2.start();
customerThread3.start();
}
}
Even though I have used 'synchronized' I could notice that some times Thread3 is picking up prior to Thread2 and could you please help me to resolve this issue and to acheive the following results ?
(1) Always customerThread1 should take the positions first and then
followed by customerThread2 and then customerThread3 (etc...)
(2) As soon as the A's position is freed by customerThread1, the
position should be immediately picked up by customerThread2 (rather
than customerThread2 and customerThread3 waiting till all positions
are done by customerThread1).And as soon as customerThread2 finishes
position 'A', then customerThread3 should pick it up, etc..
(3) As soon as the position (A, B, etc..) is freed/available, the next
customerThread should pick it up immediately.
(4) The solution should avoid all race conditions
There are several fundamental problems.
You have broken code and already noticed that it doesn’t work. But instead of asking how to fix that broken code, you are asking for alternatives with higher performance. You will never manage to write working programs with that attitude.
Apparently, you have no idea, what synchronized does. It acquires a lock on a particular object instance which can be held by one thread only. Therefore, all code fragments synchronizing on the same object are enforced to be executed ordered, with the necessary memory visibility. So your code fails for two reasons:
You are creating multiple instances of Status accessing the same objects referenced by a static variable. Since all threads use different locks, this access is entirely unsafe.
Your occupyOrClear is declared synchronized, but your method isClear is not. So even if all threads were using the same lock instance for occupyOrClear, the result of isClear remained unpredictable due to its unsafe access to the map.
You have code of the form
if(status.isClear(position)) { status.occupyOrClear(position, false); …
which matches the check-then-act anti-pattern. Even if each of these two method calls were thread-safe, this sequence still remained unsafe, because between these two invocations, everything can happen, most notably, the condition, the thread just checked, may change without the thread noticing. So two or more threads could invoke isClear, receiving true and then proceed with occupyOrClear.
You are using Thread.sleep.
You can try with the following pseudocode:
main() {
//some concurrent queues, eg ConcurrentLinkedQueue
Queue t1Tasks = new Queue("A","B","C");
Queue t2Tasks = new Queue();
Queue t3Tasks = new Queue();
Thread t1 = new PThread(t1Tasks,t2Tasks,"customer1");
Thread t2 = new PThread(t2Tasks,t3Tasks,"customer2");
Thread t3 = new PThread(t3Tasks,null,"customer3");
}
PThread {
Queue q1,q2;
PThread(Queue q1, Queue q2,...){}
run() {
while (item = q1.get()) {
//process item
q2.put(item); //to be processed by next thread
}
}
}
So let's say I'm creating and starting a bunch of threads in a for loop, that is being executed in the run method of a launcher thread. Let's also say that I want to be able to interrupt the launcher thread and all threads that the thread has created, and I do this through a button.
So something like this -
try{
for(int i = 0; i < n;i++){
Worker currThread = new Worker(someArgs);
workerThreads.add(currThread);
currThread.start();
}
} catch (InterruptedException e){
e.printStackTrace();
}
BUTTON-
public void actionPerformed(ActionEvent arg0) {
List<Worker> threads = launchThread.getWorkerThreads();
for(int i = 0; i < threads.size();i++){
threads.get(i).interrupt();
}
launchThread.interrupt();
}
Now, let's say that I want to make it so that the interrupts cannot occur at the same time as thread creation. I think a way to do this would be to construct a dummy object and put both pieces of code inside a lock
synchronized(dummyObject){
//thread creation or interruption code here (shown above)
}
Will this way work? I ask because I'm not sure how to test to see if it will.
Start the threads separately from creating them.
for(int i = 0; i < n; i++) {
Worker currThread = new Worker(someArgs);
workerThreads.add(currThread);
}
// later
for (Worker w : workerThreads) {
w.start();
}
If that's still not enough, your dummyObject synchronization should work just fine.
// You probably need to make this a (private final) field
Object lock = new Object();
// later
synchronized (lock) {
for(int i = 0; i < n; i++) {
Worker currThread = new Worker(someArgs);
workerThreads.add(currThread);
w.start();
}
}
// later still
public void actionPerformed(ActionEvent arg0) {
synchronized (lock) {
// interruption code here
}
}
The concept of synchronization remains the same however complicated are the underlying operations to be executed.
As you specified, there are two types of mutually exclusive tasks (thread creation and interruption). So locking is pretty much the canonical tool for the job.
I have a question regarding threading in Java. In my code,
...
client.doSth();
// now need to get hold of the thread that is initiated by 'client'
(get a reference to the 'client' thread)
// now kills it
(kills the 'client' thread)
...
So what I would like to know is: in the first brackets, how do I programmatically get hold of a reference to the 'client' thread (NOT the main thread the program is running on), and in the second brackets, how do I properly kill it, i.e. without using the depreciated stop() method.
Many thanks.
To show the Thread tree do like that :
you can do like this :
// Find the root thread group
ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
while (root.getParent() != null) {
root = root.getParent();
}
// Visit each thread group
visit(root, 0);
// This method recursively visits all thread groups under `group'.
public static void visit(ThreadGroup group, int level) {
// Get threads in `group'
int numThreads = group.activeCount();
Thread[] threads = new Thread[numThreads*2];
numThreads = group.enumerate(threads, false);
System.out.println(" ");
// Enumerate each thread in `group'
for (int i=0; i<numThreads; i++) {
// Get thread
Thread thread = threads[i];
System.out.println(thread.toString());
}
// Get thread subgroups of `group'
int numGroups = group.activeGroupCount();
ThreadGroup[] groups = new ThreadGroup[numGroups*2];
numGroups = group.enumerate(groups, false);
// Recursively visit each subgroup
for (int i=0; i<numGroups; i++) {
visit(groups[i], level+1);
}
}
You can choose to call a method that shows the stackTrace for a specified Thread id :
System.out.println(thread.dumpStack());
Now you have the id to kill :
int idToKill = 2;
int active = Thread.activeCount();
System.out.println("currently active threads: " + active);
Thread all[] = new Thread[active];
Thread.enumerate(all);
for (int i = 0; i < active; i++) {
System.out.println(i + ": " + all[i]);
if(idToKill == i)
((Thread) all[i]).interrupt();
}
Edit:
after rereading the question I am not sure any more if you have access to the client code. If you do, well you can revise it and not even use thread but java.util.concurrent.ExecutorService or the likes.. yet
Since the code is not your own... you are on your own to stop it.
ThreadGroup class is designed for. Managing partial programs or modules is not exactly easy and usually it takes some already established framework. Ensuring some 3rd party code will behave and be nice and all it's not always possible. It should include context classloader and what not but here is a skimmed version of how it's done.
Still there might be something you can do to break the bone of the intruder. Assuming stop()/close(), etc has been used, some tricks like ThreadDeath during logging and so on.
ThreadGroup g=new ThreadGroup("client X group");
Runnable r=new Runnable(){
public void run(){
client.doSmth();//assuming a new thread is started...
}
}
Thread t= new Thread(g, r, "clientStarter");
t.start();
//stopping, last resort code, it's usually more complicated than just thread.stop, though
//now you can enumerate threads of the ThreadGroup
synchronized(g){//sync ensures no more threads will be created, use it w/ extreme caution
Thread[] threads = new Thread[g.activeCount()];
for(Thread thread:threads){
if(thread==null) break;
thread.stop();//
//cannot join in sync of ThreadGroup, do not use it here
}
}
Good luck!
you can create a stpSth() method in your Client and call that to stop it
public class Client(){
private Thread t;
volatile private boolean stop;//volatile to ensure visibility across threads
public doSth(){
stop=false;
Runnable r = new Runnable(){
#Override
public void run(){
while(!stop){
//do stuff and periodically and ensure that interrupts bubble through
}
}
};
t = new Thread(r);
t.start();
}
public void stopSht(){
stop=true;
t.interupt();
}
}
I see in the comment you are using kryonet API.
kryonet supplies a stop() method for Client objects. If you start the client using start() creates a Thread, and stop() should stop it.
Following is a snippet to start and stop kryonet servers and clients, showing the active threads at various points in the process. The 2 second sleep is to let the threads come to an end when they are requested to stop.
import java.io.IOException;
import java.util.Arrays;
import com.esotericsoftware.kryonet.Client;
import com.esotericsoftware.kryonet.Server;
public class KryonetAndThreads {
public static void main(String[] args) throws IOException,
InterruptedException {
Server s = new Server();
s.start();
s.bind(1927);
printThreads("server started");
Client c = new Client();
c.start();
c.connect(5000, "LOCALHOST", 1927);
printThreads("client connected");
Server s1 = s;
s.stop();
printThreads("server stopped");
s = new Server();
s.start();
s.bind(1928);
printThreads("new server started"); // new server thread will be last on
// the list.
c.stop();
printThreads("client stopped");
c.start();
c.connect(5000, "localhost", 1928);
printThreads("client connected to second server");
c.stop();
s.stop();
s1.stop();
printThreads("both stopped");
}
private static void printThreads(String message)
throws InterruptedException {
// tick:
Thread.sleep(2000L);
Thread[] threads = new Thread[Thread.activeCount()];
Thread.enumerate(threads);
System.out.println(message + " : " + Arrays.asList(threads));
}
}
If the doSth() method returns a Thread object, you can do the following;
Thread t = client.doSth();
t.interrupt();