使线程以正确的方式工作

时间:2010-12-07 17:29:35

标签: java multithreading concurrency

我刚刚开始学习线程并且误解了它们是如何工作的。

这是我的班级:

public class MyThread extends Thread {
    private static int NUM = 0;
    private int id;

    public MyThread() {
        id = NUM++;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new MyThread().start(); 
        }
    }

    public void run() {
        System.out.println(id + " started");

        try {
            Process p = Runtime.getRuntime().exec("javac -version");
            p.waitFor();
        } catch (Exception e) {
            System.out.println("Call a doc!");
        }

        System.out.println(id + " finished");
    }
}

/*
Just a sidenote.
I am creating new javac process just to slow an application down.
Simple System.out.println(…) is a way faster.
*/

为什么我总是首先获得所有“...已启动”消息,然后在“...已完成”消息之后?无论我开始有多少线程,我总是看到:

0 started
1 started
2 started
3 started
4 started
5 started
6 started
7 started
8 started
9 started
0 finished
1 finished
3 finished
4 finished
8 finished
5 finished
2 finished
6 finished
9 finished
7 finished

线程的目的不是并行化执行吗? 也许我需要同步一些东西?还是犯了不小心的错误?还是...?
请解释一下。

更新

为什么我不看,让我们说:

0 started
1 started
0 finished
2 started
1 finished
2 finished

谢谢大家的治疗。

5 个答案:

答案 0 :(得分:2)

线程是并行的。否则你会看到每个线程在下一个“开始”之前“完成”

减慢线程的一种简单方法是使用Thread.sleep(10 * 1000);睡10秒(10,000毫秒)

编辑:查看线程交错的一种简单方法是使用固定大小的线程池。

ExecutorService pool = Executors.newFixedThreadPool(4);
for (int i = 0; i < 10; i++) {
    final int id = i;
    pool.submit(new Callable<Void>() {
        public Void call() throws InterruptedException {
            System.out.println(id + " started");
            Thread.sleep(1000);
            System.out.println(id + " finished");
            return null;
        }
    });
}

打印

0 started
1 started
2 started
3 started
0 finished
4 started
1 finished
5 started
2 finished
6 started
3 finished
7 started
4 finished
8 started
5 finished
6 finished
9 started
7 finished
8 finished
9 finished

答案 1 :(得分:2)

看起来不错。您可以从输出中看到线程正在交错。线程正在开始,获得上下文切换,并被调度程序选中,例如,您可以看到线程8在线程5之前跳转的位置。如果所有的数字都是一致的,那就很奇怪,但这似乎很好。

像Peter Lawrey建议的那样使用睡眠时间,这样你就可以更容易地改变每个线程的使用时间。正如您的示例所示,启动一个进程需要花费很多时间才能使所有线程在任何完成之前启动。

答案 2 :(得分:1)

如果在run()方法中放置一个简单的循环来计算从1到20的计数,你可能会看到执行的交错更好。

答案 3 :(得分:1)

multi-threading and parallel processing之间存在差异......请查看此内容......

答案 4 :(得分:1)

如果您想要查看“随机”的开头和结尾,您可能需要添加

Thread.sleep(new Random().nextInt(1000)); 

或类似于线程。