重新启动 java 线程



我想知道为什么执行器服务实际上可以多次执行相同的线程。因为线程的通常生命周期在终止的 afaik 上结束。

所以

public class TestThread extends Thread {
  AtomicInteger counter = new AtomicInteger(0);
  @Override
  public void run() {
    System.out.printf("%dn", counter.addAndGet(1));
  }
  public static void main(String[] args) throws InterruptedException {
    ExecutorService es = Executors.newCachedThreadPool();
    TestThread t = new TestThread();
    es.execute(t);
    es.execute(t);
    es.shutdown();
  }
}

这适用于我实际上期望非法状态例外的地方,例如在这种情况下:

t.start();
t.start(); =>BAM!

非常感谢帮助解开执行背后的魔力!

ExecutorService.execute(Runnable)

新的Thread实例包装它们。如果还打印线程 ID,

@Override
public void run() {
    System.out.printf("%d %d%n", counter.addAndGet(1),
        Thread.currentThread().getId());
}

您将看到两个不同的线程正在运行。例如

1 10
2 11

ExecutorService 永远不会重新启动线程。 线程永远无法重新启动。

ExecutorService 是一个线程。 它管理一组长时间运行的线程,每个线程都能够执行许多任务。

当你的代码调用一些 ExeuctorService(es 和一些 Runnable(的 es.submit(r) 时;submit 函数会将你的 runnable 添加到阻塞队列中。

由 ExecutorService 管理的每个线程都有一个 run(( 方法,如下所示:

public void run() {
    while (true) {
        Runnable task = queue.take();
        task.run();
    }
}

当然,由于异常和 shutdown(( 机制,它比这更复杂,但这是基本思想。 池线程基本上永远运行,等待任务执行。

Thread 对象的

start() 方法不会调用两次,实际上甚至不会调用一次:只使用对象的Runnable接口。实际的Thread是用每个execute()创建的,每个都委托给你的run()方法。

您无法重新启动线程,但可以检测多次使用的线程;

测试代码:

package com.stackoverflow.test;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
public class TestOfCachedThreadPool {
  private static final int AMOUNT = 1000000;
  private static final class TestThread implements Runnable {
    private Map<Long, Long> mapOfUsage;
    private TestThread(Map<Long, Long> mapOfUsage) {
      this.mapOfUsage = mapOfUsage;
    }
    @Override
    public void run() {
      synchronized (mapOfUsage) {
        Long numberOfThreads=mapOfUsage.get(Thread.currentThread().getId());
        if(numberOfThreads==null){
          mapOfUsage.put(Thread.currentThread().getId(), 1l);
        }else{
          mapOfUsage.put(Thread.currentThread().getId(), ++numberOfThreads);
        }
      }
    }
  }
  public static void main(String[] args) {
    ThreadFactory threadFactory = Executors.defaultThreadFactory();
    final Map<Long, Long> mapOfUsage = new HashMap<>(AMOUNT * 2);
    ExecutorService service = Executors.newCachedThreadPool();
    for(int i=0;i<AMOUNT;i++){
      service.execute(threadFactory.newThread(new TestThread(mapOfUsage)));
    }
    for(Map.Entry<Long, Long> entry: mapOfUsage.entrySet()){
      if(entry.getValue()>1){
        System.out.println("Thread with id "+entry.getKey() +" was used "+entry.getValue()+ " times");
      }
    }
  }
}

输出:

ID 为 9 的线程被使用了 27198 次

ID 为 11 的线程被使用了 1810 次

ID 为 13 的线程被使用了 1294 次

ID 为 15 的线程被使用了 3347 次

ID 为 17 的线程被使用了 6709 次

ID 为 19 的线程被使用了 7259 次

ID 为 21 的线程被使用了 39335 次

ID 为 23 的线程被使用了 13552 次

ID 为 25 的线程被使用了 535 次

ID 为 27 的螺纹被使用了 19533 次

ID 为 29 的线程被使用了 113495 次

ID 为 31 的线程被使用了 62713 次

ID 为 35 的线程已使用 94103 次

ID 为 33 的线程已使用 53641 次

ID 为 5328 的螺纹被使用了 18922 次

ID 为 16388 的线程已使用 28501 次

ID 为 16384 的线程被使用了114677次

ID 为 16386 的线程被使用了 39 次

ID 为 16698 的线程已使用 60450 次

ID 123096的线程被使用了 19944 次

ID 123102 的线程已使用 60961 次

ID 为 123115 的线程被使用了 24246 次

ID 275492 的线程被使用了 108399 次

ID 为 275490 的线程已使用 11973 次

ID 380143 的线程被使用了 10433 次

ID 为 363358 的线程已使用 55989 次

ID 692626的线程被使用了 6016 次

ID 为 909079 的线程已使用 25782 次

ID 为 965801 的线程被使用了 32 次

ID 948919的线程被使用了 1782 次

ID 为 948872 的线程使用了 4 次

ID 为 938802 的线程被使用 24 次

ID 923558的线程被使用了 7302 次

相关内容

  • 没有找到相关文章

最新更新