1 类中的同步线程
Posted
技术标签:
【中文标题】1 类中的同步线程【英文标题】:Synchronized Threads in 1 Class 【发布时间】:2013-03-09 20:14:27 【问题描述】:我一直在寻找一种成功使用多线程和同步的方法。我试过使用 wait() 和 notify(),但我的线程仍然不同步。 我有一个更大的项目,但简而言之,我需要它使用 setter 方法(在本例中为 thread1)运行线程预定次数,并且在每次“设置”之后,我需要使用 getter 方法(thread2)的线程运行并获取对象。 我查看了许多其他示例,但我似乎无法解决,因此任何关于为什么这不起作用的帮助或解释将不胜感激。
这有时会起作用,当线程 1 先运行时,但其他时候线程 2 先运行,因此同步不起作用。
谢谢。
import java.util.ArrayList;
public class ThreadTest
private ArrayList<Object> myList;
public ThreadTest()
myList = new ArrayList<Object>();
Thread thread1 = new Thread()
public void run()
for(int i = 0; i < 10; i++)
addToList("" + i);
;
Thread thread2 = new Thread()
public void run()
for(int i = 0; i < 10; i++)
System.out.print(myList.get(i) + " ");
;
thread1.start();
thread2.start();
public synchronized void addToList(String a)
myList.add(a);
notify();
public synchronized ArrayList<Object> getList()
try
wait();
catch (InterruptedException e)
// TODO Auto-generated catch block
e.printStackTrace();
return myList;
public static void main(String[] args)
new ThreadTest();
【问题讨论】:
getList()
方法的目的是什么?你没有使用它。
不要重新发明***。使用BlockingQueue
@bmorris591 但是如果我想要一个方形***怎么办 ;)
这似乎与任何有用甚至有启发性的东西相去甚远。所以得到了很多。这是学校作业吗?谁会分配这种垃圾?
@NathanHughes 不幸的是,糟糕的例子可能很流行,并且一次又一次地被复制,因此很难杀死它们。 vanillajava.blogspot.com.au/2012/08/…
【参考方案1】:
使用BlockingQueue
自动进行同步,使用ExecutorService
处理所有Thread
s
public void doStuff()
final Object finishSupplying = new Object();
final BlockingQueue<Object> myList = new LinkedBlockingQueue<Object>();
final Runnable supplier = new Runnable()
public void run()
for (int i = 0; i < 10; i++)
myList.add(i);
;
final Runnable consumer = new Runnable()
public void run()
while (true)
try
final Object thing = myList.take();
if(thing == finishSupplying) break;
System.out.print(thing + " ");
catch (InterruptedException ex)
Thread.currentThread().interrupt();
;
final ExecutorService exectutorService = Executors.newFixedThreadPool(2);
final Future<?> supplierHandle = exectutorService.submit(supplier);
final Future<?> consumerHandle = exectutorService.submit(consumer);
try
supplierHandle.get();
catch (InterruptedException ex)
Thread.currentThread().interrupt();
catch (ExecutionException ex)
//PROBLEMS, handle
myList.add(finishSupplying);
try
consumerHandle.get();
catch (InterruptedException ex)
Thread.currentThread().interrupt();
catch (ExecutionException ex)
//PROBLEMS, handle
完成后确保你shutdown()
ExecutorService
,否则你的程序将不会退出。
【讨论】:
【参考方案2】:当您通知时,您应该更新一个状态(正如您所拥有的),当您等待时必须在循环中检查该状态。这是必需的,因为
等待开始前的通知触发器和信号丢失 等待可能被虚假唤醒。注意:你的消费线程不会等待,因为你没有调用任何等待的东西。
有很多方法可以解决这个问题,但恕我直言,最好的解决方案是使用旨在支持这种模式的 BlockingQueue。
【讨论】:
【参考方案3】:您不应该使用 getter 和 setter 来访问整个列表,而只能从中推送和拉取元素。如前所述,BlockingQueue
是一个同步列表实现。
也就是说,如果你想自己实现,将getList替换为列表上的同步remove(0)
,它只返回ArrayList的第一个元素。
【讨论】:
以上是关于1 类中的同步线程的主要内容,如果未能解决你的问题,请参考以下文章
5.线程的八大核心基础知识之Thread和Object类中的重要方法详解