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 处理所有Threads

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类中的重要方法详解

python多线程执行类中的静态方法

J.U.C工具类中的CountDownLatch和CyclicBarrier

Java中的sleep()和wait()异同

多线程中的wait与sleep到底谁释放了锁

线程Thread中的join介绍