I want to make a test, two thread, one thread is changing the value, another thread use a while to wait the first thread, and then break and finish.But the question is the waiting thread is always running, can' stop any more. Another question is when i open the code of "System.out.println(i + " run");", all the thread can work normally, it's so strange.
import java.util.Date;
public class ThreadTestTwo {
public int a = 0, b = 0,c = 0;
public static void main(String[] args) {
System.out.println(new Date()+"start");
for (int i = 0; i < 100000; i++) {
new ThreadTestTwo().start(i);
if(i % 100000 == 0){
System.out.println(i/100000);
}
}
System.out.println(new Date()+"finish");
}
public void start(final int i){
Thread readThread = new Thread(){
#Override
public void run() {
while (true) {
if(c == 1){
b = a;
// System.out.println(i+", set b "+a);
break;
}
// System.out.println(i + " run");
}
}
};
Thread writeThread = new Thread(){
#Override
public void run() {
a = 1;
c = 1;
}
};
writeThread.setName("mywrite");
readThread.setName("myread");
System.out.println(i+" start");
writeThread.start();
readThread.start();
try {
writeThread.join();
readThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i+" end");
if(b != 1)
throw new RuntimeException("b = "+b);
}
}
The writes of one thread are NOT guaranteed to be seen for another thread unless the variables are marked as volatile or otherwise the transactions need to handled using synchronization or explicit locking
In your case, a,b,c are the instance variables accessed by multiple threads and the reader thread caches the values and so it doesn't see the writer thread's flushed value.
Please refer the below link for more details:
https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html
I advise you to read more on Threads. Here it is an interesting document from O'really: http://chimera.labs.oreilly.com/books/1234000001805/ch09.html
As for your implementation, you should be aware that the modification of one variable by a thread may not be seen by a reader thread. To combat that either use synchronised gets and sets, access the variables inside a synchronized block, or use an AtomicReference. You could also use a Lock such as ReantrantLock.
Also, if you have two threads, in which the first is waiting for the input of the second, you could use the wait() inside a synchronized block for the first, so that the second could notify() the first one when it finishes its job.
Something like this:
import java.util.Date;
public class ThreadTestTwo {
private int a = 0, b = 0,c = 0;
private final Object lock = new Object();
//Any object is good as a lock, and for a simple case as this it's fine.
//This object will work as a monitor for the synchronized blocks.
public void start(final int i){
Thread readThread = new Thread(){
#Override
public void run() {
synchronized ( lock ) {
try {
while( c != 1 ) {
lock.wait();
}
}
catch ( InterruptedException ex ) {
//Exception handling
}
b = a;
}
//System.out.println(i + " run");
}
};
Thread writeThread = new Thread(){
#Override
public void run() {
synchronized ( lock ) {
a = 1;
c = 1;
lock.notify();
}
}
};
writeThread.setName("mywrite");
readThread.setName("myread");
System.out.println(i+" start");
writeThread.start();
readThread.start();
System.out.println(i+" end");
}
public static void main(String[] args) {
System.out.println(new Date()+"start");
for (int i = 0; i < 100000; i++) {
new ThreadTestTwo().start(i);
if(i % 100000 == 0){
System.out.println(i/100000);
}
}
System.out.println(new Date()+"finish");
}
}
I would say you don't need join() with this method. But if want to wait for the second thread to start after the first is finished, you have to use join() before starting it. Like this:
writeThread.start();
try {
writeThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
readThread.start();
try {
readThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
But if you use join(), for this particular case, I would say you wouldn't need any synchronized blocks or conditions, since the second thread would only start after the death of the first one. Something like this:
public void start(final int i){
Thread readThread = new Thread(){
#Override
public void run() {
b = a;
//System.out.println(i + " run");
}
};
Thread writeThread = new Thread(){
#Override
public void run() {
a = 1;
c = 1;
}
};
writeThread.setName("mywrite");
readThread.setName("myread");
System.out.println(i+" start");
writeThread.start();
try {
writeThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
readThread.start();
try {
readThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
System.out.println(i+" end");
}
I hope I have helped.
Have a nice day. :)
It's not a good idea to use an simple int as a signal between threads because it's not thread safe.
So try to use AtomicInteger instead or make your int volatile and see what will happen.
Related
I am learning about the use of semaphores and multi threading in general but am kind of stuck. I have two threads printing G and H respectively and my objective is to alternate the outputs of each thread so that the output string is like this;
G
H
G
H
G
H
Each of the two classes has a layout similar to the one below
public class ClassA extends Thread implements Runnable{
Semaphore semaphore = null;
public ClassA(Semaphore semaphore){
this.semaphore = semaphore;
}
public void run() {
while(true)
{
try{
semaphore.acquire();
for(int i=0; i<1000; i++){
System.out.println("F");
}
Thread.currentThread();
Thread.sleep(100);
}catch(Exception e)
{
System.out.println(e.toString());
}
semaphore.release();
}
}
}
below is my main class
public static void main(String[] args) throws InterruptedException {
Semaphore semaphore = new Semaphore(1);
ClassA clasA = new ClassA(semaphore);
Thread t1 = new Thread(clasA);
ClassB clasB = new ClassB(semaphore);
Thread t2 = new Thread(clasB);
t1.start();
t2.join();
t2.start();
The output I am getting is way too different from my expected result. can anyone help me please? did I misuse the semaphore? any help?
Semaphores can't help you solve such a task.
As far as I know, JVM doesn't promise any order in thread execution. It means that if you run several threads, one thread can execute several times in a row and have more processor time than any other. So, if you want your threads to execute in a particular order you can, for the simplest example, make a static boolean variable which will play a role of a switcher for your threads. Using wait() and notify() methods will be a better way, and Interface Condition will be the best way I suppose.
import java.io.IOException;
public class Solution {
public static boolean order;
public static void main(String[] args) throws IOException, InterruptedException {
Thread t1 = new ThreadPrint("G", true);
Thread t2 = new ThreadPrint("O", false);
t1.start();
t2.start();
t2.join();
System.out.println("Finish");
}
}
class ThreadPrint extends Thread {
private String line;
private boolean order;
public ThreadPrint(String line, boolean order) {
this.line = line;
this.order = order;
}
#Override
public void run() {
int z = 0;
while (true) {
try {
for (int i = 0; i < 10; i++) {
if (order == Solution.order) {
System.out.print(line + " ");
Solution.order = !order;
}
}
sleep(100);
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
}
BTW there can be another problem cause System.out is usually an Operation System buffer and your OS can output your messages in an order on its own.
P.S. You shouldn't inherit Thread and implement Runnable at the same time
public class ClassA extends Thread implements Runnable{
because Thread class already implements Runnable. You can choose only one way which will be better for your purposes.
You should start a thread then join to it not vice versa.
t1.start();
t2.join();
t2.start();
As others have pointed out, locks themselves do not enforce any order and on top of that, you cannot be certain when a thread starts (calling Thread.start() will start the thread at some point in the future, but this might take a while).
You can, however, use locks (like a Semaphore) to enforce an order. In this case, you can use two Semaphores to switch threads on and off (alternate). The two threads (or Runnables) do need to be aware of each other in advance - a more dynamic approach where threads can "join in" on the party would be more complex.
Below a runnable example class with repeatable results (always a good thing to have when testing multi-threading). I will leave it up to you to figure out why and how it works.
import java.util.concurrent.*;
public class AlternateSem implements Runnable {
static final CountDownLatch DONE_LATCH = new CountDownLatch(2);
static final int TIMEOUT_MS = 1000;
static final int MAX_LOOPS = 10;
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
try {
AlternateSem as1 = new AlternateSem(false);
AlternateSem as2 = new AlternateSem(true);
as1.setAlternate(as2);
as2.setAlternate(as1);
executor.execute(as1);
executor.execute(as2);
if (DONE_LATCH.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
System.out.println();
System.out.println("Done");
} else {
System.out.println("Timeout");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executor.shutdownNow();
}
}
final Semaphore sem = new Semaphore(0);
final boolean odd;
AlternateSem other;
public AlternateSem(boolean odd) {
this.odd = odd;
}
void setAlternate(AlternateSem other) { this.other = other; }
void release() { sem.release(); }
void acquire() throws Exception { sem.acquire(); }
#Override
public void run() {
if (odd) {
other.release();
}
int i = 0;
try {
while (i < MAX_LOOPS) {
i++;
other.acquire();
System.out.print(odd ? "G " : "H ");
release();
}
} catch (Exception e) {
e.printStackTrace();
}
DONE_LATCH.countDown();
}
}
I am trying to do a little exercise on threads and I just started learning thread and other stuff.
import java.util.logging.Level;
import java.util.logging.Logger;
public class ThreadDemo extends Thread {
#Override
public void run() {
int count = 0;
for (int i = 0; i <= 5; i++) {
count++;
System.out.println("counting" + count);
}
if (count == 3) {
try {
Thread t = new Thread();
t.wait(5000);
System.out.println("thread waiting");
} catch (InterruptedException ex) {
Logger.getLogger(ThreadDemo.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public static void main(String[] args) {
ThreadDemo obj = new ThreadDemo();
obj.start();
}
}
Output of the given
counting1
counting2
counting3
counting4
counting5
counting6
When the test if (count == 3) is done the value of count is 6.
And your code test it only once.
You need to move the code that is out of the for loop inside it.
You need also to hold a lock on t before call wait. This is done with a synchronized block.
#Override
public void run() {
int count = 0;
for (int i = 0; i <= 5; i++) {
count++;
System.out.println("counting" + count);
// Moved block
if (count == 3) {
try {
Thread t = new Thread();
synchronized (t) {
t.wait(5000);
}
System.out.println("thread waiting");
} catch (InterruptedException ex) {
Logger.getLogger(ThreadDemo.class.getName()).log(Level.SEVERE, null, ex);
}
}
// End of moved block
}
}
The output will be
counting1
counting2
counting3
thread waiting // Note: this will be printed after 5 seconds
counting4
counting5
counting6
A similar result, but not identical can be obtained using Thread.sleep, replacing this code
Thread t = new Thread();
synchronized (t) {
t.wait(5000);
}
With the following:
Thread.sleep(5000);
A difference between Thread.sleep and Object.wait is that is possible to awake a thread waiting acquiring his lock and calling notify (or notifyAll).
Instead is not possible to awake a thread sleeping with Thread.sleep.
First of all, this is not a homework.
I have written a piece of code so that:
Thread-1 prints 1,4,7,... (diff is 3)
Thread-2 prints 2,5,8,...
Thread-3 prints 3,6,9,...
And the final output should be:
1,2,3,4,5,6,7,8,9,...
Here's the code that works wonderfully well:
package threadAlgo;
public class ControlOrder {
volatile Monitor monitor = new Monitor();
public static void main(String[] args) {
ControlOrder order = new ControlOrder();
Thread one = new Thread(new Task(order.monitor, 1));
one.setName("Thread-1");
Thread two = new Thread(new Task(order.monitor, 2));
two.setName("Thread-2");
Thread three = new Thread(new Task(order.monitor, 3));
three.setName("Thread-3");
one.start();
two.start();
three.start();
}
}
class Monitor {
int threadNumber = 1;
}
class Task implements Runnable {
private Monitor monitor;
private int myThreadNumber;
private int currentCount;
Task(Monitor monitor, int myThreadNumber) {
this.monitor = monitor;
this.myThreadNumber = myThreadNumber;
this.currentCount = myThreadNumber;
}
#Override
public void run() {
while (true) {
while (monitor.threadNumber != myThreadNumber) {
synchronized (monitor) {
try {
monitor.wait(100); //DOESN'T WORK WITHOUT THE TIMEOUT!!!
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized (monitor) {
if (monitor.threadNumber == myThreadNumber) {
System.out.println(Thread.currentThread().getName() + ": " + currentCount);
currentCount = currentCount + 3;
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (myThreadNumber == 3) {
monitor.threadNumber = 1;
} else {
monitor.threadNumber = myThreadNumber + 1;
}
monitor.notifyAll();
}
}
}
}
The only problem is that if I use wait() instead of wait(timeout), then the thread halts.
UPDATE:
Wait condition (while loop) should be inside synchronized block. A lesson for beginners, including me.
You should always
perform notifyAll/notify in conjunction with a change in state.
check the state change before using wait() in a loop.
If you call notify() and no wait() is waiting, then the signal is lost, so unless you check a state change, (or timeout) you can block forever waiting for a signal which doesn't change.
main thread creating two thread t1 and t2 run() method of these thread creating two new thread c1 and c2.I want a scenario such that until c1&c2(of t1) are alive t2 will not start executing.
In my code notify and wait are causing Runtime Exception.Since they are not in synchronised block, how to do this?
public class childTcreat2newthread {
public static void main(String[] args) throws InterruptedException {
Thread mainT=Thread.currentThread();
Target ra=new Target("a");
Thread t1=new Thread(ra);
t1.start();
t1.join();
while(ra.getC1().isAlive()==true||ra.getC2().isAlive()==true){
synchronized (mainT) {
mainT.wait();
}}
new Thread(new Target("b")).start();}}
class Target implements Runnable{
Thread c1=new Thread(new Target1("1"));
Thread c2=new Thread(new Target1("2"));
String msg;
Target(String msg){
this.msg=msg;
}
#Override
public void run() {
for(int j=0;j<100000;j++){
for(int i=0;i<10000;i++){
if(i%10000==0&&j%10000==0){System.out.print(msg);}
}}
t1.start();
t2.start();
}
public Thread getC1(){return c1;}
public Thread getC2(){return c2;}
}
class Target1 implements Runnable {
String msg;
Target1(String msg){
this.msg=msg;
}
#Override
public synchronized void run() {
for(int j=0;j<100000;j++){
for(int i=0;i<100000;i++){
if(i%100000==0&&j%10000==0){System.out.print(msg);}
}
}
try{
notifyAll();
System.out.println("K");}catch(IllegalMonitorStateException e){System.out.println("\nIllegalMonitorStateException!! in "+msg+"\n");}
}
}
wait( ) tells the calling thread to give up the monitor and go to sleep until some others thread enters the same monitor and calls notify( ).Unable to get same monitor when calling notify.How to do this?
As for my understanding both the thread t1 & t2 does not have common object here to which these are accessing so which object we should have to pass in synchronised lock to call wait() and notify()?
as #JB Nizet pointed out you should use join to wait fot thread termination
EDIT
since you cannot use join I suggest you to use a CountDownLatch since
its documentation states:
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
Which is what you asked for.
SECOND EDIT
Here is a modified version of your code that wait for thread termination using a HomeMade CountDownLatch that uses wait and notify.
import java.util.concurrent.CountDownLatch;
public class childTcreat2newthread {
public static void main(String[] args) throws InterruptedException {
MyCountDownLatch doneSignal = new MyCountDownLatch(2);
Target ra = new Target("a",doneSignal);
Thread t1 = new Thread(ra);
t1.start();
doneSignal.await();
System.out.println("after await ");
MyCountDownLatch doneSignal1 = new MyCountDownLatch(2);
new Thread(new Target("b",doneSignal1)).start();
}
}
class Target implements Runnable {
private Thread c1;
private Thread c2;
String msg;
Target(String msg, MyCountDownLatch doneSignal) {
this.msg = msg;
c1 = new Thread(new Target1("1",doneSignal));
c2 = new Thread(new Target1("2",doneSignal));
}
#Override
public void run() {
System.out.println("Start of Target " + msg);
for (int j = 0; j < 100000; j++) {
for (int i = 0; i < 10000; i++) {
if (i % 10000 == 0 && j % 10000 == 0) {
System.out.print(msg);
}
}
}
c1.start();
c2.start();
// try {
// c1.join();
// c2.join();
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
System.out.println("End of Target " + msg);
}
public Thread getC1() {
return c1;
}
public Thread getC2() {
return c2;
}
}
class Target1 implements Runnable {
String msg;
private MyCountDownLatch doneSignal;
Target1(String msg, MyCountDownLatch doneSignal) {
this.msg = msg;
this.doneSignal=doneSignal;
}
#Override
public void run() {
System.out.println("Start of Target1 " + msg);
for (int j = 0; j < 100000; j++) {
for (int i = 0; i < 100000; i++) {
if (i % 100000 == 0 && j % 10000 == 0) {
System.out.print(msg);
}
}
}
try {
System.out.println("K");
doneSignal.countDown();
System.out.println("End of Target1 " + msg);
} catch (IllegalMonitorStateException e) {
System.out.println("\nIllegalMonitorStateException!! in " + msg
+ "\n");
}
}
}
class MyCountDownLatch {
private int waitersNum;
public MyCountDownLatch(int waitersNum) {
this.waitersNum=waitersNum;
}
public synchronized void countDown() {
waitersNum--;
if (waitersNum==0) {
notifyAll();
}
}
public synchronized void await() throws InterruptedException {
wait();
}
}
notify, notifyAll, wait calls should be done in the monitor of the same object. There should be a shared object like Object and you should build your logic around that. For example :
public class ClassA{
Object lockObject=new Object();
//Thread A will call this method
public void methodA(){
synchronized(lockObject){
while(!aCondition)
lockObject.wait();
}
}
//Thread B will call this method
public void methodB(){
synchronized(lockObject){
aCondition=true;
lockObject.notify();
}
}
}
MI have a program that starts with for loop and it spins for 10 times, and one loop lasts one second. I need to handle a signal (CTRL+C) and while handling it, it should do it's own for loop, and after it stops, then I should return to the main loop. I've managed to do almost everything above, but the loops don't execute separately. They do it parallel. Hope you can help... thanks :)
BTW, my code is:
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class MySig {
public static void shhh(int s){ //s -> seconds :)
s = s*1000;
try{
Thread.sleep(s);
}catch(InterruptedException e){
System.out.println("Uh-oh :(");
}
}
public static void main(String[] args){
Signal.handle(new Signal("INT"), new SignalHandler () {
public void handle(Signal sig) {
for(int i=0; i<5; i++){
System.out.println("+");
shhh(1);
}
}
});
for(int i=0; i<10; i++) {
shhh(1);
System.out.println(i+"/10");
}
}
}
Right, according to the docs, SignalHandler is executed in a separate thread:
...when the VM receives a signal, the special C signal handler creates a
new thread (at priority Thread.MAX_PRIORITY) to run the registered
Java signal handler..
If you want to stop your main loop while the handler is executing, you can add a locking mechanism, something like this:
private static final ReentrantLock lock = new ReentrantLock(true);
private static AtomicInteger signalCount = new AtomicInteger(0);
public static void shhh(int s) { // s -> seconds :)
s = s * 1000;
try {
System.out.println(Thread.currentThread().getName() + " sleeping for "
+ s + "s...");
Thread.sleep(s);
} catch (InterruptedException e) {
System.out.println("Uh-oh :(");
}
}
public static void main(String[] args) throws Exception {
Signal.handle(new Signal("INT"), new SignalHandler() {
public void handle(Signal sig) {
// increment the signal counter
signalCount.incrementAndGet();
// Acquire lock and do all work
lock.lock();
try {
for (int i = 0; i < 5; i++) {
System.out.println("+");
shhh(1);
}
} finally {
// decrement signal counter and unlock
signalCount.decrementAndGet();
lock.unlock();
}
}
});
int i = 0;
while (i < 10) {
try {
lock.lock();
// go back to wait mode if signals have arrived
if (signalCount.get() > 0)
continue;
System.out.println(i + "/10");
shhh(1);
i++;
} finally {
// release lock after each unit of work to allow handler to jump in
lock.unlock();
}
}
}
There might be a better locking strategy.