如何同步线程

时间:2012-03-17 01:59:20

标签: java multithreading

在这个多线程程序中,当我运行它时,我总是以一些随机顺序获得输出。但我想知道是否有任何方法可以让这个程序在同步模式下工作。就像我嚼它然后第一个线程它应该打印出所有内容,然后第二个线程它应该打印出来的东西,然后第三个线程它应该打印出所有等等。所以每个线程的样本输出应该是这样的 - / p>

Task 1 Started
original: Hello World
Difference:- 0
Task 1 Ended

Task 2 Started
original: Hello World
Difference:- 0
Task 2 Ended

............
............


Task 15 Started
original: Hello World
Difference:- 0
Task 15 Ended

这是我的下面的程序。任何建议将不胜感激。

class ThreadTask implements Runnable {
    private int id;

    public ThreadTask(int id) {
        this.id = id;
    }

    public synchronized void run() {

        System.out.println("Task " + id + " Started ");

        String originalString = "Hello World";

        System.out.println("original: " + originalString);

        System.out.println("Task " + id + " Ended ");

    }
}

public class TestPool {

    public static void main(String[] args) throws InterruptedException {
        int size = 5; //Integer.parseInt(args[0]);

        // create thread pool with given size
        ExecutorService service = Executors.newFixedThreadPool(size); 

        // queue some tasks
        for(int i = 1; i <= 3 * size; i++) {
            service.submit(new ThreadTask(i));
        }


        // wait for termination        
        service.shutdown();
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 
    }
}

3 个答案:

答案 0 :(得分:4)

您对Jakub的答案评论如下:

  

在我开始学习线程时,你能给我一些关于我的代码的示例基础吗?这对我有很大的帮助。

Jakub所说的是强制线程以固定顺序运行会破坏首先使用线程的目的。 想一想。


如果您确实希望/需要您的示例按顺序运行任务,您可以这样做:

for (int i = 1; i <= 3 * size; i++) {
        new ThreadTask(i).run();
}

即。只需在当前线程中运行runnable。

或者您可以将最大池大小设置为1,这会强制服务按顺序运行任务。 (当然,这会破坏使用线程的重点。你不会以这种方式得到任何并行性。)


更明智的方法是让每个线程在Future中返回其结果,然后让主线程从每个未来(按所需顺序)获取值并打印它。基本上,您希望允许线程以任何顺序运行(并行,如果您有多个核心),但在访问结果时强制执行排序。

答案 1 :(得分:2)

线程的本质是它们可以同时运行,如果你希望它们按顺序运行,就不要使用Thread。

还有另一种要求,也许你想要几个工作(同时),但按照给定的顺序。在这种情况下,我强烈建议您实施排队系统。也就是说,建立一个像

这样的队列
Queue <C> q

一个帖子

class T implements Runnable {
     public void run() {
         while (!q.empty()) {
            // Do something
         }
     }
}

您可以通过ExecutorService使用Runnable,就像您使用过的代码一样。

您还可以在之前代码的“执行某事”部分中将一些元素添加到队列中,然后您可以自己控制作业的顺序。

答案 2 :(得分:0)

您可以保存对前一个线程的引用,并使用join()将下一个线程连接到上一个线程。这将确保线程将以一系列运行(下一个线程不会启动,除非前一个完成)。但这样做的目的是让我望而却步。

public class TestPool
{

    static class ThreadTask extends Thread
    {
        private int id;
        private Thread previous;

        public ThreadTask(int id, Thread previous){
            this.id = id;
            this.previous = previous;
        }

        public void run(){
            if(previous != null){
                try{
                    previous.join();
                }
                catch(InterruptedException e){
                    e.printStackTrace();
                }
            }

            System.out.println("Task " + id + " Started ");

            String originalString = "Hello World";

            System.out.println("original: " + originalString);

            System.out.println("Task " + id + " Ended ");

        }
    }

    public static void main(String[] args) throws InterruptedException{
        int size = 5; // Integer.parseInt(args[0]);

        // create thread pool with given size
        ExecutorService service = Executors.newFixedThreadPool(size);

        Thread previous = null;
        // queue some tasks
        for(int i = 1; i <= 3 * size; i++){
            Thread thread = new ThreadTask(i, previous);
            previous = thread;
            thread.start();
            //service.submit(thread);
        }

        // wait for termination
        //service.shutdown();
        //service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
    }
}

未经测试,sry。我不知道ExecutorService正在做什么,它可能会打破这个。请注意,我需要成为ThreadRunnable是不够的。此外,run()无需同步,因为每次执行只会调用一次。并且您不应该使用run()启动线程,而应使用start()

编辑:我只是试图运行它,并且ExecutorService正在提供帮助。如果你只是启动线程(就像我的代码那样),那么它就可以了。