1

我刚开始使用线程。我编写了一个主类,它设置并启动 100 个线程,等待 5 秒然后中断它们(至少我认为它是这样做的):

public static void main(String[] args) {

    List<Thread> threads = new ArrayList<Thread>();

    for (int i = 0; i < 100; i++) {
        Thread t = new Thread(new Walker());
        threads.add(t);
    }

    System.out.println("Starting threads...");

    for (Thread thread : threads) {
        thread.start();
    }

    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        // don't do anything
    }

    System.out.println("Time's up - Terminating threads...");
    for (Thread t : threads) {
        t.interrupt();
        System.out.print(".");
    }
    for (Thread t : threads) {
        try {
            t.join(10);
        } catch (InterruptedException e) {
            // don't do anything
        }
    }
    System.out.println("");
    System.out.println("All done.");
}

线程看起来有点像这样:

public class Walker implements Runnable {
    public void run() {
        for (int i = 0;; i++) {
            //do some complicated stuff that takes some time
            System.out.println(Thread.currentThread().getName() + ":" + i);
            if (Thread.interrupted()) {
                break;
            }
        }
    }
}

现在,我得到的输出是主线程开始中断线程,但一些子线程在终止之前继续运行几次(即循环迭代),例如

开始线程...
Thread-1:0
Thread-2:0
Thread-1:1
Thread-3:0
[...]
时间到了 - 终止线程...
......Thread-1:60
线程-1:61
...Thread-1:62
Thread-2:55
..全部完成。
[即使在这里,线程的输出有时也会继续 - 在 join() 之后]

那时我并不完全理解可以为单个线程分配足够的处理器时间来运行几次——我预计在主线程有机会中断它之前最多再运行一次。

但是,虽然我现在看到在主线程有机会终止(即中断)它之前执行一段时间(长时间)绝对没问题,但我仍然想知道:是否有一种简单的方法来中断所有子线程是否及时从主线程?(通过线程的构造函数设置“生存时间”,然后在 Walker 类中对其进行测试不是我想要的。)

另外:是否有可能执行最后一个打印语句,然后查看各个线程的一些输出 - 在所有线程都加入()之后?(也许我在其他地方有一个小故障;实际的代码有点复杂......)

4

3 回答 3

2

The problem you observe is probably due to how System.out.println works. It is a synchronized method. So a likely explanation is:

  • when calling System.out.print("."); after t.interrupt();, your main thread acquires the lock to print
  • before the lock is released, worker threads arrive at System.out.println(Thread.currentThread().getName() + ":" + i); and wait for the lock
  • when the main thread releases the lock, all the worker threads that were waiting print their progress.
  • the main thread arrives at System.out.print("."); again and has to wait for the print lock to be available, etc.

Regarding the fact that you see more prints from the worker threads after "All Done" is printed: you only join for 10 ms, so it is possible that it is not enough and a thread is not finished within 10ms of being interrupted. If you just use join() you should not see that any longer.

Example of Worker class that reproduces the behaviour you observe:

class Walker implements Runnable {

    public void run() {
        for (int i = 0;; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
                //do not respond to interruption too quickly on purpose
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {}
                Thread.currentThread().interrupt();
            }
            System.out.println(Thread.currentThread().getName() + ":" + i);
            if (Thread.interrupted()) {
                break;
            }
        }
    }
}
于 2013-06-04T12:38:22.410 回答
2

使用 ExecutorService 会更容易,例如

    int nThreads = 100;
    ExecutorService ex = Executors.newFixedThreadPool(nThreads);
    for (int i = 0; i < nThreads; i++) {
        ex.execute(new Walker());
    }
    Thread.sleep(5000);
    ex.shutdownNow();
于 2013-06-04T12:33:11.457 回答
0
Maybe I have a glitch somewhere else; the actual code is a bit more complex...

是的,这是一个小故障,不幸的是它不是一个简单的 set 1 属性,java 方面。

如果代码是商业的、复杂的,那么您可以分配更多的时间来编写一些本机库,用于主要的 Os 类型。有了这个帮助,您可以轻松地随心所欲地使用线程。

第一次在开发和理解线程如何在本机操作系统端工作时会产生开销,而不仅仅是调用带有一些参数的函数:)

不确定,如果有帮助,则存在故障。

于 2013-06-04T12:22:03.007 回答