Lưu ý (như những người khác được chỉ ra là tốt) mà bạn phải sử dụng cùng một đối tượng để khóa/đồng bộ hóa trong cả hai chủ đề.
Nếu bạn muốn chủ đề chính của mình tiếp tục ngay lập tức sau khi notify
được gọi, bạn phải từ bỏ khóa tạm thời. Nếu không, wait
sẽ chỉ được gọi sau khi chuỗi thứ hai rời khỏi khối synchronized
. Và nó không bao giờ là một ý tưởng tốt để giữ một khóa trong một tính toán chạy dài!
Một cách làm thế nào để đạt được là sử dụng wait(int)
vào khóa thay vì sleep
, vì wait
phiên bản khóa đồng bộ hóa tạm thời:
public class Tester {
private static final Object lock = new Object();
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
synchronized (lock) {
try {
System.out.println("wating for t to complete");
lock.wait();
System.out.println("wait over");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class MyRunnable implements Runnable {
public void run() {
System.out.println("entering run method");
synchronized (lock) {
System.out.println("entering syncronised block");
lock.notify();
try {
lock.wait(1000); // relinquish the lock temporarily
} catch (InterruptedException ex) {
System.out.println("got interrupted");
}
System.out.println("leaving syncronized block");
}
System.out.println("leaving run method");
}
}
}
Tuy nhiên, sử dụng các nguyên thủy ở mức độ thấp có thể rất dễ bị lỗi và tôi 'd không khuyến khích sử dụng chúng. Thay vào đó, tôi khuyên bạn nên sử dụng nguyên thủy cấp cao của Java cho điều đó. Ví dụ, bạn có thể sử dụng CountDownLatch
cho phép một thread chờ đợi cho đến khi chủ đề khác đếm ngược tới zero:
import java.util.concurrent.*;
public class TesterC {
private static final CountDownLatch latch = new CountDownLatch(1);
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
System.out.println("wating for t to complete");
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("wait over");
}
static class MyRunnable implements Runnable {
public void run() {
System.out.println("entering run method");
try {
latch.countDown();
Thread.sleep(1000);
} catch (InterruptedException ex) {
System.out.println("got interrupted");
}
System.out.println("leaving run method");
}
}
}
Ở đây bạn không cần phải đồng bộ hóa bất cứ điều gì, chốt làm mọi thứ cho bạn. Có nhiều nguyên thủy khác mà bạn có thể sử dụng - các semaphores, một bộ trao đổi, các hàng đợi an toàn thread, vv. Explorer gói java.util.concurrent
.
Có lẽ giải pháp thậm chí tốt hơn là sử dụng API cấp cao hơn, chẳng hạn như Akka cung cấp. Ở đó bạn làm việc với Actors hoặc Software transactional memory, có thể được soạn dễ dàng và dành cho bạn hầu hết các vấn đề tương tranh.
Nguồn
2013-07-01 08:09:39
Bạn không đồng bộ hóa trên cùng một đối tượng – MadProgrammer
MyRunnable.this == r! = T –
@ raul8 Chỉnh sửa câu hỏi và dán trong câu trả lời làm cho câu trả lời đúng không hợp lệ. Sẽ tốt hơn nếu bạn thêm một câu hỏi khác. –