Enforce printing sequence but threads waiting on each other after one iteration
up vote
2
down vote
favorite
I am having trouble resolving this one thread waiting on another issue (even after viewing several questions posts). Here is what I am trying to do: I want one thread (called sub-thread) to print 10 times under outer-loop with 2 iterations; then another (boss-thread) to print 100 times under outer-loop with 2 iterations provided that sub-thread goes first. It will look something like this:
Sub Thread- iter = 1
Sub Thread- iter = 2
...
Sub Thread- iter = 10
Boss Thread- iter = 1
Boss Thread- iter = 2
...
Boss Thread- iter = 100
This sub-thread and boss-thread printing sequence will continue for 2 times (outer-loop).
My implementation has unpredicatable results, i.e. it prints out first iteration of sub-thread 10 times then halts there or it rarely prints out all statements and run through both the inner-loop and outer-loop. I use wait()
and notify()
to enable communication bewteen threads. I am not sure if I place synchronized
block in the wrong place or I just mis-used the wait()
and notify()
pairs. Here's the code:
public class Main {
public static void main(String args) {
Main ic = new Main();
Thread t1 = new Thread(ic.new Th1(), "Boss Thread-");
Thread t2 = new Thread(ic.new Th2(), "Sub Thread-");
t2.start();
t1.start();
}
// Boss Thread
private class Th1 implements Runnable {
@Override
public void run() {
System.out.println("TH1 RUNS FIRST");
synchronized (Main.class) { // lock outside of outer loop so
// boss thread can pick up the next iteration
for (int i = 0; i < 2; i++) {
// wait, let the sub-thread run first
try {
Main.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// print iterations
for (int j = 0; j < 100; j++) {
System.out.println(Thread.currentThread().getName() + " iter = " + (j + 1));
}
System.out.println("end of boss outer----------------------" + (i + 1));
// wake up sub-thread and let it knows inner-iteration finished
Main.class.notify();
}
}
}
}
// Sub Thread
private class Th2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (Main.class) { // lock up Th2
// print iterations
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getName() + " iter = " + (j + 1));
}
// wake up other boss thread and let it know inner-iteration finished
Main.class.notify();
// wait for other thread to run
try {
Main.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end of Sub outer---------------------- " + (i + 1));
}
}
}
}
}
Extra assistance needed: would someone tell me if synchronized
is a good way of locking shared resource or other better alternatives are out there? Say ReentrantLock
? Also, are notify()
and wait()
a good means to implement inter-threads communication or there are better means to make this less error-prone and more efficient?
java multithreading wait notify
add a comment |
up vote
2
down vote
favorite
I am having trouble resolving this one thread waiting on another issue (even after viewing several questions posts). Here is what I am trying to do: I want one thread (called sub-thread) to print 10 times under outer-loop with 2 iterations; then another (boss-thread) to print 100 times under outer-loop with 2 iterations provided that sub-thread goes first. It will look something like this:
Sub Thread- iter = 1
Sub Thread- iter = 2
...
Sub Thread- iter = 10
Boss Thread- iter = 1
Boss Thread- iter = 2
...
Boss Thread- iter = 100
This sub-thread and boss-thread printing sequence will continue for 2 times (outer-loop).
My implementation has unpredicatable results, i.e. it prints out first iteration of sub-thread 10 times then halts there or it rarely prints out all statements and run through both the inner-loop and outer-loop. I use wait()
and notify()
to enable communication bewteen threads. I am not sure if I place synchronized
block in the wrong place or I just mis-used the wait()
and notify()
pairs. Here's the code:
public class Main {
public static void main(String args) {
Main ic = new Main();
Thread t1 = new Thread(ic.new Th1(), "Boss Thread-");
Thread t2 = new Thread(ic.new Th2(), "Sub Thread-");
t2.start();
t1.start();
}
// Boss Thread
private class Th1 implements Runnable {
@Override
public void run() {
System.out.println("TH1 RUNS FIRST");
synchronized (Main.class) { // lock outside of outer loop so
// boss thread can pick up the next iteration
for (int i = 0; i < 2; i++) {
// wait, let the sub-thread run first
try {
Main.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// print iterations
for (int j = 0; j < 100; j++) {
System.out.println(Thread.currentThread().getName() + " iter = " + (j + 1));
}
System.out.println("end of boss outer----------------------" + (i + 1));
// wake up sub-thread and let it knows inner-iteration finished
Main.class.notify();
}
}
}
}
// Sub Thread
private class Th2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (Main.class) { // lock up Th2
// print iterations
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getName() + " iter = " + (j + 1));
}
// wake up other boss thread and let it know inner-iteration finished
Main.class.notify();
// wait for other thread to run
try {
Main.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end of Sub outer---------------------- " + (i + 1));
}
}
}
}
}
Extra assistance needed: would someone tell me if synchronized
is a good way of locking shared resource or other better alternatives are out there? Say ReentrantLock
? Also, are notify()
and wait()
a good means to implement inter-threads communication or there are better means to make this less error-prone and more efficient?
java multithreading wait notify
please post your code directly in your question to avoid relying on external sources that may disappear in the future
– njzk2
Nov 10 at 5:15
@njzk2 As per requested, I posted the code in the description. Thanks.
– Learner80239
Nov 10 at 6:03
There are 2 issues I can see in your code: 1st is that you have no way of guaranteeing which thread acquires the lock onMain.class
first. 2nd is that when you call notify, you are still holding the lock (as in the doc, "The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object.") although that part should be fine as there is a wait right after.
– njzk2
Nov 10 at 7:35
@njzk2 I'm not sure about "guaranteeing" a thread owning a lock. Are you suggesting usingLock
or there is a way to enforce that along withsynchronized
? Also, thanks for pointing "holding the lock when invokingnotify()
. But I have to usenotify()
under some kind ofsynchronized
block since it's only used if it owns a shared object (monitor), right?
– Learner80239
Nov 10 at 8:42
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I am having trouble resolving this one thread waiting on another issue (even after viewing several questions posts). Here is what I am trying to do: I want one thread (called sub-thread) to print 10 times under outer-loop with 2 iterations; then another (boss-thread) to print 100 times under outer-loop with 2 iterations provided that sub-thread goes first. It will look something like this:
Sub Thread- iter = 1
Sub Thread- iter = 2
...
Sub Thread- iter = 10
Boss Thread- iter = 1
Boss Thread- iter = 2
...
Boss Thread- iter = 100
This sub-thread and boss-thread printing sequence will continue for 2 times (outer-loop).
My implementation has unpredicatable results, i.e. it prints out first iteration of sub-thread 10 times then halts there or it rarely prints out all statements and run through both the inner-loop and outer-loop. I use wait()
and notify()
to enable communication bewteen threads. I am not sure if I place synchronized
block in the wrong place or I just mis-used the wait()
and notify()
pairs. Here's the code:
public class Main {
public static void main(String args) {
Main ic = new Main();
Thread t1 = new Thread(ic.new Th1(), "Boss Thread-");
Thread t2 = new Thread(ic.new Th2(), "Sub Thread-");
t2.start();
t1.start();
}
// Boss Thread
private class Th1 implements Runnable {
@Override
public void run() {
System.out.println("TH1 RUNS FIRST");
synchronized (Main.class) { // lock outside of outer loop so
// boss thread can pick up the next iteration
for (int i = 0; i < 2; i++) {
// wait, let the sub-thread run first
try {
Main.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// print iterations
for (int j = 0; j < 100; j++) {
System.out.println(Thread.currentThread().getName() + " iter = " + (j + 1));
}
System.out.println("end of boss outer----------------------" + (i + 1));
// wake up sub-thread and let it knows inner-iteration finished
Main.class.notify();
}
}
}
}
// Sub Thread
private class Th2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (Main.class) { // lock up Th2
// print iterations
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getName() + " iter = " + (j + 1));
}
// wake up other boss thread and let it know inner-iteration finished
Main.class.notify();
// wait for other thread to run
try {
Main.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end of Sub outer---------------------- " + (i + 1));
}
}
}
}
}
Extra assistance needed: would someone tell me if synchronized
is a good way of locking shared resource or other better alternatives are out there? Say ReentrantLock
? Also, are notify()
and wait()
a good means to implement inter-threads communication or there are better means to make this less error-prone and more efficient?
java multithreading wait notify
I am having trouble resolving this one thread waiting on another issue (even after viewing several questions posts). Here is what I am trying to do: I want one thread (called sub-thread) to print 10 times under outer-loop with 2 iterations; then another (boss-thread) to print 100 times under outer-loop with 2 iterations provided that sub-thread goes first. It will look something like this:
Sub Thread- iter = 1
Sub Thread- iter = 2
...
Sub Thread- iter = 10
Boss Thread- iter = 1
Boss Thread- iter = 2
...
Boss Thread- iter = 100
This sub-thread and boss-thread printing sequence will continue for 2 times (outer-loop).
My implementation has unpredicatable results, i.e. it prints out first iteration of sub-thread 10 times then halts there or it rarely prints out all statements and run through both the inner-loop and outer-loop. I use wait()
and notify()
to enable communication bewteen threads. I am not sure if I place synchronized
block in the wrong place or I just mis-used the wait()
and notify()
pairs. Here's the code:
public class Main {
public static void main(String args) {
Main ic = new Main();
Thread t1 = new Thread(ic.new Th1(), "Boss Thread-");
Thread t2 = new Thread(ic.new Th2(), "Sub Thread-");
t2.start();
t1.start();
}
// Boss Thread
private class Th1 implements Runnable {
@Override
public void run() {
System.out.println("TH1 RUNS FIRST");
synchronized (Main.class) { // lock outside of outer loop so
// boss thread can pick up the next iteration
for (int i = 0; i < 2; i++) {
// wait, let the sub-thread run first
try {
Main.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// print iterations
for (int j = 0; j < 100; j++) {
System.out.println(Thread.currentThread().getName() + " iter = " + (j + 1));
}
System.out.println("end of boss outer----------------------" + (i + 1));
// wake up sub-thread and let it knows inner-iteration finished
Main.class.notify();
}
}
}
}
// Sub Thread
private class Th2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (Main.class) { // lock up Th2
// print iterations
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getName() + " iter = " + (j + 1));
}
// wake up other boss thread and let it know inner-iteration finished
Main.class.notify();
// wait for other thread to run
try {
Main.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end of Sub outer---------------------- " + (i + 1));
}
}
}
}
}
Extra assistance needed: would someone tell me if synchronized
is a good way of locking shared resource or other better alternatives are out there? Say ReentrantLock
? Also, are notify()
and wait()
a good means to implement inter-threads communication or there are better means to make this less error-prone and more efficient?
java multithreading wait notify
java multithreading wait notify
edited Nov 10 at 5:59
asked Nov 10 at 4:10
Learner80239
113
113
please post your code directly in your question to avoid relying on external sources that may disappear in the future
– njzk2
Nov 10 at 5:15
@njzk2 As per requested, I posted the code in the description. Thanks.
– Learner80239
Nov 10 at 6:03
There are 2 issues I can see in your code: 1st is that you have no way of guaranteeing which thread acquires the lock onMain.class
first. 2nd is that when you call notify, you are still holding the lock (as in the doc, "The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object.") although that part should be fine as there is a wait right after.
– njzk2
Nov 10 at 7:35
@njzk2 I'm not sure about "guaranteeing" a thread owning a lock. Are you suggesting usingLock
or there is a way to enforce that along withsynchronized
? Also, thanks for pointing "holding the lock when invokingnotify()
. But I have to usenotify()
under some kind ofsynchronized
block since it's only used if it owns a shared object (monitor), right?
– Learner80239
Nov 10 at 8:42
add a comment |
please post your code directly in your question to avoid relying on external sources that may disappear in the future
– njzk2
Nov 10 at 5:15
@njzk2 As per requested, I posted the code in the description. Thanks.
– Learner80239
Nov 10 at 6:03
There are 2 issues I can see in your code: 1st is that you have no way of guaranteeing which thread acquires the lock onMain.class
first. 2nd is that when you call notify, you are still holding the lock (as in the doc, "The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object.") although that part should be fine as there is a wait right after.
– njzk2
Nov 10 at 7:35
@njzk2 I'm not sure about "guaranteeing" a thread owning a lock. Are you suggesting usingLock
or there is a way to enforce that along withsynchronized
? Also, thanks for pointing "holding the lock when invokingnotify()
. But I have to usenotify()
under some kind ofsynchronized
block since it's only used if it owns a shared object (monitor), right?
– Learner80239
Nov 10 at 8:42
please post your code directly in your question to avoid relying on external sources that may disappear in the future
– njzk2
Nov 10 at 5:15
please post your code directly in your question to avoid relying on external sources that may disappear in the future
– njzk2
Nov 10 at 5:15
@njzk2 As per requested, I posted the code in the description. Thanks.
– Learner80239
Nov 10 at 6:03
@njzk2 As per requested, I posted the code in the description. Thanks.
– Learner80239
Nov 10 at 6:03
There are 2 issues I can see in your code: 1st is that you have no way of guaranteeing which thread acquires the lock on
Main.class
first. 2nd is that when you call notify, you are still holding the lock (as in the doc, "The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object.") although that part should be fine as there is a wait right after.– njzk2
Nov 10 at 7:35
There are 2 issues I can see in your code: 1st is that you have no way of guaranteeing which thread acquires the lock on
Main.class
first. 2nd is that when you call notify, you are still holding the lock (as in the doc, "The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object.") although that part should be fine as there is a wait right after.– njzk2
Nov 10 at 7:35
@njzk2 I'm not sure about "guaranteeing" a thread owning a lock. Are you suggesting using
Lock
or there is a way to enforce that along with synchronized
? Also, thanks for pointing "holding the lock when invoking notify()
. But I have to use notify()
under some kind of synchronized
block since it's only used if it owns a shared object (monitor), right?– Learner80239
Nov 10 at 8:42
@njzk2 I'm not sure about "guaranteeing" a thread owning a lock. Are you suggesting using
Lock
or there is a way to enforce that along with synchronized
? Also, thanks for pointing "holding the lock when invoking notify()
. But I have to use notify()
under some kind of synchronized
block since it's only used if it owns a shared object (monitor), right?– Learner80239
Nov 10 at 8:42
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
After some thoughts and efforts, I've come up with an "implementation" that "meets" my expectation as described in the question post. I have made some changes to the wait
and notify
pairs and added an isTh2RunFirst
flag to assist the communication of the two threads. Here's the code:
public class InterThCom {
// flag default to false for checking if sub-thread
// gets the lock first
private boolean isTh2RunFirst = false;
public static void main(String args) {
InterThCom itc = new InterThCom();
Thread t1 = new Thread(itc.new Th1(), "Boss-thread-");
Thread t2 = new Thread(itc.new Th2(), "Sub-thread-");
t1.start();
t2.start();
}
private class Th1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (InterThCom.class) { // lock up inner-loop
// boss-thread gets the lock first
// wait for sub-thread and let it run;
// otherwise, skip this check
if (isTh2RunFirst == false) {
// wait for sub-thread, if boss-thread gets the lock first
try {
InterThCom.class.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
// print iteration 100 times
for (int j = 0; j < 100; j++) {
System.out.println(Thread.currentThread().getName() + " iter-" + (j + 1));
}
// done printing 100 times
// sub-thread should run already at this point
isTh2RunFirst = true;
// This print helps split boss-th and sub-th prints
System.out.println(Thread.currentThread().getName() + " outer-loop iter:" + (i + 1));
// wake up sub-thread
InterThCom.class.notify();
// wait for sub-thread
try {
InterThCom.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
private class Th2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (InterThCom.class) {
// print iteration 10 times
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getName() + " iter-" + (j + 1));
}
// done printing 10 times
// sub-thread already prints j iteration
isTh2RunFirst = true;
// This print helps split boss-th and sub-th prints
System.out.println(Thread.currentThread().getName() + " outer-loop iter:" + (i + 1));
// wake up boss-thread
InterThCom.class.notify();
// wait for boss-thread
try {
InterThCom.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized (InterThCom.class) {
// boss-thread is waiting at the last iteration, so wake it up
InterThCom.class.notify();
}
}
}
}
I also posted a Code Review post if anyone feels like addressing to "proper" implementation (in terms of industry practices and efficiency) of thread-communication in detail for this specific case or others in general.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53235919%2fenforce-printing-sequence-but-threads-waiting-on-each-other-after-one-iteration%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
After some thoughts and efforts, I've come up with an "implementation" that "meets" my expectation as described in the question post. I have made some changes to the wait
and notify
pairs and added an isTh2RunFirst
flag to assist the communication of the two threads. Here's the code:
public class InterThCom {
// flag default to false for checking if sub-thread
// gets the lock first
private boolean isTh2RunFirst = false;
public static void main(String args) {
InterThCom itc = new InterThCom();
Thread t1 = new Thread(itc.new Th1(), "Boss-thread-");
Thread t2 = new Thread(itc.new Th2(), "Sub-thread-");
t1.start();
t2.start();
}
private class Th1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (InterThCom.class) { // lock up inner-loop
// boss-thread gets the lock first
// wait for sub-thread and let it run;
// otherwise, skip this check
if (isTh2RunFirst == false) {
// wait for sub-thread, if boss-thread gets the lock first
try {
InterThCom.class.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
// print iteration 100 times
for (int j = 0; j < 100; j++) {
System.out.println(Thread.currentThread().getName() + " iter-" + (j + 1));
}
// done printing 100 times
// sub-thread should run already at this point
isTh2RunFirst = true;
// This print helps split boss-th and sub-th prints
System.out.println(Thread.currentThread().getName() + " outer-loop iter:" + (i + 1));
// wake up sub-thread
InterThCom.class.notify();
// wait for sub-thread
try {
InterThCom.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
private class Th2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (InterThCom.class) {
// print iteration 10 times
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getName() + " iter-" + (j + 1));
}
// done printing 10 times
// sub-thread already prints j iteration
isTh2RunFirst = true;
// This print helps split boss-th and sub-th prints
System.out.println(Thread.currentThread().getName() + " outer-loop iter:" + (i + 1));
// wake up boss-thread
InterThCom.class.notify();
// wait for boss-thread
try {
InterThCom.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized (InterThCom.class) {
// boss-thread is waiting at the last iteration, so wake it up
InterThCom.class.notify();
}
}
}
}
I also posted a Code Review post if anyone feels like addressing to "proper" implementation (in terms of industry practices and efficiency) of thread-communication in detail for this specific case or others in general.
add a comment |
up vote
0
down vote
After some thoughts and efforts, I've come up with an "implementation" that "meets" my expectation as described in the question post. I have made some changes to the wait
and notify
pairs and added an isTh2RunFirst
flag to assist the communication of the two threads. Here's the code:
public class InterThCom {
// flag default to false for checking if sub-thread
// gets the lock first
private boolean isTh2RunFirst = false;
public static void main(String args) {
InterThCom itc = new InterThCom();
Thread t1 = new Thread(itc.new Th1(), "Boss-thread-");
Thread t2 = new Thread(itc.new Th2(), "Sub-thread-");
t1.start();
t2.start();
}
private class Th1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (InterThCom.class) { // lock up inner-loop
// boss-thread gets the lock first
// wait for sub-thread and let it run;
// otherwise, skip this check
if (isTh2RunFirst == false) {
// wait for sub-thread, if boss-thread gets the lock first
try {
InterThCom.class.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
// print iteration 100 times
for (int j = 0; j < 100; j++) {
System.out.println(Thread.currentThread().getName() + " iter-" + (j + 1));
}
// done printing 100 times
// sub-thread should run already at this point
isTh2RunFirst = true;
// This print helps split boss-th and sub-th prints
System.out.println(Thread.currentThread().getName() + " outer-loop iter:" + (i + 1));
// wake up sub-thread
InterThCom.class.notify();
// wait for sub-thread
try {
InterThCom.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
private class Th2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (InterThCom.class) {
// print iteration 10 times
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getName() + " iter-" + (j + 1));
}
// done printing 10 times
// sub-thread already prints j iteration
isTh2RunFirst = true;
// This print helps split boss-th and sub-th prints
System.out.println(Thread.currentThread().getName() + " outer-loop iter:" + (i + 1));
// wake up boss-thread
InterThCom.class.notify();
// wait for boss-thread
try {
InterThCom.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized (InterThCom.class) {
// boss-thread is waiting at the last iteration, so wake it up
InterThCom.class.notify();
}
}
}
}
I also posted a Code Review post if anyone feels like addressing to "proper" implementation (in terms of industry practices and efficiency) of thread-communication in detail for this specific case or others in general.
add a comment |
up vote
0
down vote
up vote
0
down vote
After some thoughts and efforts, I've come up with an "implementation" that "meets" my expectation as described in the question post. I have made some changes to the wait
and notify
pairs and added an isTh2RunFirst
flag to assist the communication of the two threads. Here's the code:
public class InterThCom {
// flag default to false for checking if sub-thread
// gets the lock first
private boolean isTh2RunFirst = false;
public static void main(String args) {
InterThCom itc = new InterThCom();
Thread t1 = new Thread(itc.new Th1(), "Boss-thread-");
Thread t2 = new Thread(itc.new Th2(), "Sub-thread-");
t1.start();
t2.start();
}
private class Th1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (InterThCom.class) { // lock up inner-loop
// boss-thread gets the lock first
// wait for sub-thread and let it run;
// otherwise, skip this check
if (isTh2RunFirst == false) {
// wait for sub-thread, if boss-thread gets the lock first
try {
InterThCom.class.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
// print iteration 100 times
for (int j = 0; j < 100; j++) {
System.out.println(Thread.currentThread().getName() + " iter-" + (j + 1));
}
// done printing 100 times
// sub-thread should run already at this point
isTh2RunFirst = true;
// This print helps split boss-th and sub-th prints
System.out.println(Thread.currentThread().getName() + " outer-loop iter:" + (i + 1));
// wake up sub-thread
InterThCom.class.notify();
// wait for sub-thread
try {
InterThCom.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
private class Th2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (InterThCom.class) {
// print iteration 10 times
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getName() + " iter-" + (j + 1));
}
// done printing 10 times
// sub-thread already prints j iteration
isTh2RunFirst = true;
// This print helps split boss-th and sub-th prints
System.out.println(Thread.currentThread().getName() + " outer-loop iter:" + (i + 1));
// wake up boss-thread
InterThCom.class.notify();
// wait for boss-thread
try {
InterThCom.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized (InterThCom.class) {
// boss-thread is waiting at the last iteration, so wake it up
InterThCom.class.notify();
}
}
}
}
I also posted a Code Review post if anyone feels like addressing to "proper" implementation (in terms of industry practices and efficiency) of thread-communication in detail for this specific case or others in general.
After some thoughts and efforts, I've come up with an "implementation" that "meets" my expectation as described in the question post. I have made some changes to the wait
and notify
pairs and added an isTh2RunFirst
flag to assist the communication of the two threads. Here's the code:
public class InterThCom {
// flag default to false for checking if sub-thread
// gets the lock first
private boolean isTh2RunFirst = false;
public static void main(String args) {
InterThCom itc = new InterThCom();
Thread t1 = new Thread(itc.new Th1(), "Boss-thread-");
Thread t2 = new Thread(itc.new Th2(), "Sub-thread-");
t1.start();
t2.start();
}
private class Th1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (InterThCom.class) { // lock up inner-loop
// boss-thread gets the lock first
// wait for sub-thread and let it run;
// otherwise, skip this check
if (isTh2RunFirst == false) {
// wait for sub-thread, if boss-thread gets the lock first
try {
InterThCom.class.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
// print iteration 100 times
for (int j = 0; j < 100; j++) {
System.out.println(Thread.currentThread().getName() + " iter-" + (j + 1));
}
// done printing 100 times
// sub-thread should run already at this point
isTh2RunFirst = true;
// This print helps split boss-th and sub-th prints
System.out.println(Thread.currentThread().getName() + " outer-loop iter:" + (i + 1));
// wake up sub-thread
InterThCom.class.notify();
// wait for sub-thread
try {
InterThCom.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
private class Th2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
synchronized (InterThCom.class) {
// print iteration 10 times
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getName() + " iter-" + (j + 1));
}
// done printing 10 times
// sub-thread already prints j iteration
isTh2RunFirst = true;
// This print helps split boss-th and sub-th prints
System.out.println(Thread.currentThread().getName() + " outer-loop iter:" + (i + 1));
// wake up boss-thread
InterThCom.class.notify();
// wait for boss-thread
try {
InterThCom.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized (InterThCom.class) {
// boss-thread is waiting at the last iteration, so wake it up
InterThCom.class.notify();
}
}
}
}
I also posted a Code Review post if anyone feels like addressing to "proper" implementation (in terms of industry practices and efficiency) of thread-communication in detail for this specific case or others in general.
edited Nov 10 at 17:40
answered Nov 10 at 17:33
Learner80239
113
113
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53235919%2fenforce-printing-sequence-but-threads-waiting-on-each-other-after-one-iteration%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
please post your code directly in your question to avoid relying on external sources that may disappear in the future
– njzk2
Nov 10 at 5:15
@njzk2 As per requested, I posted the code in the description. Thanks.
– Learner80239
Nov 10 at 6:03
There are 2 issues I can see in your code: 1st is that you have no way of guaranteeing which thread acquires the lock on
Main.class
first. 2nd is that when you call notify, you are still holding the lock (as in the doc, "The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object.") although that part should be fine as there is a wait right after.– njzk2
Nov 10 at 7:35
@njzk2 I'm not sure about "guaranteeing" a thread owning a lock. Are you suggesting using
Lock
or there is a way to enforce that along withsynchronized
? Also, thanks for pointing "holding the lock when invokingnotify()
. But I have to usenotify()
under some kind ofsynchronized
block since it's only used if it owns a shared object (monitor), right?– Learner80239
Nov 10 at 8:42