我能得到一个完整的简单场景,即教程,建议这应该如何使用,特别是与队列?
当前回答
你看过这个Java教程吗?
此外,我建议您在真正的软件中远离这类东西。使用它很好,这样您就知道它是什么,但是并发性到处都有陷阱。如果您正在为其他人构建软件,最好使用更高级别的抽象和同步集合或JMS队列。
至少我是这么做的。我不是并发专家,所以我尽量避免手工处理线程。
其他回答
不是一个队列的例子,但非常简单:)
class MyHouse {
private boolean pizzaArrived = false;
public void eatPizza(){
synchronized(this){
while(!pizzaArrived){
wait();
}
}
System.out.println("yumyum..");
}
public void pizzaGuy(){
synchronized(this){
this.pizzaArrived = true;
notifyAll();
}
}
}
以下要点: 1)永远不要做
if(!pizzaArrived){
wait();
}
总是使用while(condition),因为
A)线程偶尔会被唤醒 从等待状态变为无存在状态 任何人都可以通知。(即使当 送披萨的没敲钟 有人会决定试试吃 披萨)。 b)你应该检查 条件再次获得后 同步锁。比如说披萨 不要永远存在。你保持清醒, 排队买披萨,但不是 每个人都能吃。如果你没有 检查,你可能会吃到纸!:) (也许更好的例子是 而(! pizzaExists) {wait ();}。
2)在调用wait/nofity之前,你必须持有锁(synchronized)。线程还必须在唤醒前获得锁。
3)尽量避免在同步块中获得任何锁,并努力不调用外来方法(你不确定它们在做什么的方法)。如果必须这样做,请确保采取措施避免死锁。
4)小心使用notify()。坚持使用notifyAll()直到你知道你在做什么。
5)最后,但并非最不重要的,阅读Java并发实践!
例子
public class myThread extends Thread{
@override
public void run(){
while(true){
threadCondWait();// Circle waiting...
//bla bla bla bla
}
}
public synchronized void threadCondWait(){
while(myCondition){
wait();//Comminucate with notify()
}
}
}
public class myAnotherThread extends Thread{
@override
public void run(){
//Bla Bla bla
notify();//Trigger wait() Next Step
}
}
线程中wait()和notifyall()的例子。
一个同步的静态数组列表被用作资源,如果数组列表为空,则调用wait()方法。一旦为数组列表添加了元素,就调用Notify()方法。
public class PrinterResource extends Thread{
//resource
public static List<String> arrayList = new ArrayList<String>();
public void addElement(String a){
//System.out.println("Add element method "+this.getName());
synchronized (arrayList) {
arrayList.add(a);
arrayList.notifyAll();
}
}
public void removeElement(){
//System.out.println("Remove element method "+this.getName());
synchronized (arrayList) {
if(arrayList.size() == 0){
try {
arrayList.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
arrayList.remove(0);
}
}
}
public void run(){
System.out.println("Thread name -- "+this.getName());
if(!this.getName().equalsIgnoreCase("p4")){
this.removeElement();
}
this.addElement("threads");
}
public static void main(String[] args) {
PrinterResource p1 = new PrinterResource();
p1.setName("p1");
p1.start();
PrinterResource p2 = new PrinterResource();
p2.setName("p2");
p2.start();
PrinterResource p3 = new PrinterResource();
p3.setName("p3");
p3.start();
PrinterResource p4 = new PrinterResource();
p4.setName("p4");
p4.start();
try{
p1.join();
p2.join();
p3.join();
p4.join();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Final size of arraylist "+arrayList.size());
}
}
即使你特别要求wait()和notify(),我觉得这句话仍然足够重要:
Josh Bloch, Effective Java第二版,第69项:更喜欢并发实用程序来等待和通知(强调他的):
考虑到正确使用等待和通知的困难,您应该使用更高级别的并发实用程序[…]与java.util.concurrent提供的高级语言相比,直接使用wait和notify就像用“并发汇编语言”编程。很少有理由在新代码中使用wait和notify。
你看过这个Java教程吗?
此外,我建议您在真正的软件中远离这类东西。使用它很好,这样您就知道它是什么,但是并发性到处都有陷阱。如果您正在为其他人构建软件,最好使用更高级别的抽象和同步集合或JMS队列。
至少我是这么做的。我不是并发专家,所以我尽量避免手工处理线程。
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap