如何在另一个线程之前执行一个线程?
How execute a thread before another?
有个小问题想问你
我有两个线程:
HelloThread
- 这将打印 "hello" 五次。
GoodbyeThread
- 这将打印 "Goodbye" 五次。
我想先 HelloThread
运行 完成后 GoodbyeThread
运行.
我已经用信号量解决了这个问题(但是信号量并不是真正的 java 方式,它更像是 C 方式)。
HelloThread.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package modifiedthreadhellogoodbye;
import static java.lang.Thread.sleep;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.concurrent.Semaphore;
class HelloThread implements Runnable {
private final Object lock;
//private final Semaphore lock;
public HelloThread(Semaphore lock) {
this.lock = lock;
}
public HelloThread(Object lock) {
this.lock = lock;
}
@Override
public void run() {
int pause;
synchronized (lock) {
for (int i = 0; i < 5; i++) {
System.out.println("Hello!");
pause = (int) (Math.random() * 1000);
try {
sleep(pause);
} catch (InterruptedException ex) {
Logger.getLogger(HelloThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
lock.notifyAll();
System.out.println("Outsite hello");
}
//lock.release();
}
}
GoodbyeThread.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package modifiedthreadhellogoodbye;
import static java.lang.Thread.sleep;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;
class GoodbyeThread implements Runnable {
int pause;
//private final Semaphore lock;
private final Object lock;
public GoodbyeThread(Semaphore lock) {
this.lock = lock;
}
public GoodbyeThread(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
System.out.println("Inside the synchronized");
try {
lock.wait();
} catch (InterruptedException ex) {
Logger.getLogger(GoodbyeThread.class.getName()).log(Level.SEVERE, null, ex);
}
//lock.acquire();
for (int i = 0; i < 5; i++) {
System.out.println("Goodbye");
pause = (int) (Math.random() * 1000);
try {
sleep(pause);
} catch (InterruptedException ex) {
Logger.getLogger(GoodbyeThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
这是我的 class 谁 运行 主题 :
public class ModifiedThreadObject {
private final Object lock = new Object();
//private final Semaphore lock = new Semaphore(0);
public ModifiedThreadObject() {
HelloThread hello = new HelloThread(lock);
GoodbyeThread goodbye = new GoodbyeThread(lock);
Thread t1 = new Thread(hello);
Thread t2 = new Thread(goodbye);
t1.start();
t2.start();
}
}
主要思想是 GoodbyeThread
应该 wait()
来自 HelloThread
的信号。
如果 GoodbyeThread
首先是 运行,它工作得很好,但是 HelloThread
运行 首先我有以下输出:
Hello!
Hello!
Hello!
Hello!
Hello!
Outsite hello
Inside the synchronized
HelloThread
发送 notifyAll()
,但没有人在等待,所以 "signal" 丢失了 ...
有人有想法吗?
首先,我质疑在这里使用单独的线程。如果你想让一件事发生在另一件事之后,就用一个线程。
但是,很容易等到一个线程完成 - 只需使用 join
:
Thread t1 = new Thread(hello);
Thread t2 = new Thread(goodbye);
t1.start();
t1.join();
t2.start();
这样您就不需要在 "hello" 或 "goodbye" 代码中进行任何同步。
如果您想要更复杂的东西,我建议您查看 java.util.concurrent
包。虽然您 可以 使用 wait()
和 notify()
,但使用更高级别的构造通常是更好的主意。例如,对于 producer/consumer 场景,您可能希望使用 BlockingQueue
而不是自己全部实现。
您可以在 CountDownLatch
的帮助下实现,简单示例:
import java.util.concurrent.CountDownLatch;
public class Test {
public static void main(String... s){
final CountDownLatch cdl = new CountDownLatch(1);
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
int i = 5;
while((i--)>0)
System.out.println("hello");
cdl.countDown();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("goodbye");
}
});
t2.start();
t1.start();
}
}
虽然 John Skeet 提供了执行此类操作的正确方法,但了解程序流程错误的确切含义也可能很有用。
在GoodbyeThread
中:
synchronized (lock) {
System.out.println("Inside the synchronized");
try {
lock.wait();
}
所以,拿到锁后,你非要等待?问题在于 HelloThread
在 GoodbyeThread
获取它时已经终止;当 HelloThread
调用 notifyAll
时,它什么都不做,因为还没有人在等待锁。
另一个问题是Semaphore
的使用。如所写,您的 类 不使用 Semaphore
的任何功能,事实上,如果给定的话,会将其转换为 Object
。您应该从代码中删除所有提及 Semaphore
的内容,因为这是不必要的并且可能会造成混淆。
有个小问题想问你
我有两个线程:
HelloThread
- 这将打印 "hello" 五次。GoodbyeThread
- 这将打印 "Goodbye" 五次。
我想先 HelloThread
运行 完成后 GoodbyeThread
运行.
我已经用信号量解决了这个问题(但是信号量并不是真正的 java 方式,它更像是 C 方式)。
HelloThread.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package modifiedthreadhellogoodbye;
import static java.lang.Thread.sleep;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.concurrent.Semaphore;
class HelloThread implements Runnable {
private final Object lock;
//private final Semaphore lock;
public HelloThread(Semaphore lock) {
this.lock = lock;
}
public HelloThread(Object lock) {
this.lock = lock;
}
@Override
public void run() {
int pause;
synchronized (lock) {
for (int i = 0; i < 5; i++) {
System.out.println("Hello!");
pause = (int) (Math.random() * 1000);
try {
sleep(pause);
} catch (InterruptedException ex) {
Logger.getLogger(HelloThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
lock.notifyAll();
System.out.println("Outsite hello");
}
//lock.release();
}
}
GoodbyeThread.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package modifiedthreadhellogoodbye;
import static java.lang.Thread.sleep;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;
class GoodbyeThread implements Runnable {
int pause;
//private final Semaphore lock;
private final Object lock;
public GoodbyeThread(Semaphore lock) {
this.lock = lock;
}
public GoodbyeThread(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
System.out.println("Inside the synchronized");
try {
lock.wait();
} catch (InterruptedException ex) {
Logger.getLogger(GoodbyeThread.class.getName()).log(Level.SEVERE, null, ex);
}
//lock.acquire();
for (int i = 0; i < 5; i++) {
System.out.println("Goodbye");
pause = (int) (Math.random() * 1000);
try {
sleep(pause);
} catch (InterruptedException ex) {
Logger.getLogger(GoodbyeThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
这是我的 class 谁 运行 主题 :
public class ModifiedThreadObject {
private final Object lock = new Object();
//private final Semaphore lock = new Semaphore(0);
public ModifiedThreadObject() {
HelloThread hello = new HelloThread(lock);
GoodbyeThread goodbye = new GoodbyeThread(lock);
Thread t1 = new Thread(hello);
Thread t2 = new Thread(goodbye);
t1.start();
t2.start();
}
}
主要思想是 GoodbyeThread
应该 wait()
来自 HelloThread
的信号。
如果 GoodbyeThread
首先是 运行,它工作得很好,但是 HelloThread
运行 首先我有以下输出:
Hello!
Hello!
Hello!
Hello!
Hello!
Outsite hello
Inside the synchronized
HelloThread
发送 notifyAll()
,但没有人在等待,所以 "signal" 丢失了 ...
有人有想法吗?
首先,我质疑在这里使用单独的线程。如果你想让一件事发生在另一件事之后,就用一个线程。
但是,很容易等到一个线程完成 - 只需使用 join
:
Thread t1 = new Thread(hello);
Thread t2 = new Thread(goodbye);
t1.start();
t1.join();
t2.start();
这样您就不需要在 "hello" 或 "goodbye" 代码中进行任何同步。
如果您想要更复杂的东西,我建议您查看 java.util.concurrent
包。虽然您 可以 使用 wait()
和 notify()
,但使用更高级别的构造通常是更好的主意。例如,对于 producer/consumer 场景,您可能希望使用 BlockingQueue
而不是自己全部实现。
您可以在 CountDownLatch
的帮助下实现,简单示例:
import java.util.concurrent.CountDownLatch;
public class Test {
public static void main(String... s){
final CountDownLatch cdl = new CountDownLatch(1);
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
int i = 5;
while((i--)>0)
System.out.println("hello");
cdl.countDown();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("goodbye");
}
});
t2.start();
t1.start();
}
}
虽然 John Skeet 提供了执行此类操作的正确方法,但了解程序流程错误的确切含义也可能很有用。
在GoodbyeThread
中:
synchronized (lock) {
System.out.println("Inside the synchronized");
try {
lock.wait();
}
所以,拿到锁后,你非要等待?问题在于 HelloThread
在 GoodbyeThread
获取它时已经终止;当 HelloThread
调用 notifyAll
时,它什么都不做,因为还没有人在等待锁。
另一个问题是Semaphore
的使用。如所写,您的 类 不使用 Semaphore
的任何功能,事实上,如果给定的话,会将其转换为 Object
。您应该从代码中删除所有提及 Semaphore
的内容,因为这是不必要的并且可能会造成混淆。