1

我试图了解一些关于newSingleThreadExecutor- 下面如何说它按顺序执行任务,当没有ThreadFactory提到时。

public static ExecutorService newSingleThreadExecutor()

创建一个使用单个工作线程在无界队列上运行的 Executor。(但请注意,如果该单线程在关闭前的执行过程中因失败而终止,则如果需要执行后续任务,则新线程将取代它。)任务保证按顺序执行,并且不会有多个任务处于活动状态在任何给定时间。与其他等效newFixedThreadPool(1)的不同,返回的执行程序保证不能重新配置以使用额外的线程。

public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory)

创建一个 Executor,它使用单个工作线程操作无界队列,并在需要时使用提供的 ThreadFactory 创建一个新线程。与其他等效newFixedThreadPool(1, threadFactory)的不同,返回的执行程序保证不能重新配置以使用额外的线程。

参数:

但是给出下面的示例,我使用的是 ThreadFactory :

executor = Executors.newSingleThreadExecutor(getPrioritisedFactory());
`private ThreadFactory getPrioritisedFactory() {
    ThreadFactory prioritisedFactory = new ThreadFactory() {
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r, recSocketServerThreadID);
            t.setPriority(Thread.MAX_PRIORITY);
            return t;
        }
    };
    return prioritisedFactory;
}`

似乎不再尊重顺序了。是因为线程具有相同的优先级,然后开始随机选择它们吗?使用工厂时发生的情况从 Java 帮助中不太清楚。

谢谢。


感谢您到现在为止得到的答案。这是更多代码和解释。我在高负载条件下(1000 个提交的线程)的日志中发现,首先提交的线程是在其他一些稍后提交的线程之后启动的。

该示例已简化,但 MyThread.run 方法中没有更多可以延迟日志记录的代码。

  • 1:00:01.100 DEB 新线程[id:500]
  • 1:02:01.160 DEB 新线程[id:900]
  • 1:03:01.200 WAR 启动线程 [thID:900]
  • 1:04:02.200 WAR 启动线程 [thID:500]
private ExecutorService executor;


 executor = Executors.newSingleThreadExecutor(getPrioritisedFactory());
 ....
 //Keep adding threads here
 MyThread mine=MyThread();
 System.out.println(String.format("new thread[id:%d]",
                        mine.getId()));
 executor.execute(mine);



 public class MyThread extends Thread 
 {

   @Override
    public void run() {
        long startTimeMillis = System.currentTimeMillis();
        long currentTimeMillis = System.currentTimeMillis();
        long delayMillis = currentTimeMillis - this.createTimeMillis;
        logger.warn(String.format("Started  thread [thID:%d]",
                   this.getId()));
       ........
    }

 }
4

2 回答 2

2

每个人都Executor使用 aThreadFactory来创建它需要的线程。如果您没有明确提供一个,它将采用一个默认值,它返回一个相当普通的线程,但有一个名称。

没有工厂的方法只会委托给有工厂的方法。

public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
    return new DelegatedScheduledExecutorService
        (new ScheduledThreadPoolExecutor(1));
}

执行者一开始根本没有线程,他们会在需要时创建一个。它们可以同时使用的线程数量取决于它们的配置。

如果一个线程由于某种原因死亡,他们可以创建一个新线程来替换它。SingleThreadExecutor保证永远不会使用超过 1。

可以保证您的代码按顺序执行,但不能保证它始终是同一个线程。

于 2014-01-22T12:05:51.557 回答
0

Executors.newSingleThreadExecutor() 实际上给了你一个 ExecutorService 实例,它保证它一次只使用一个线程来执行你提交的任务。您提交的任务将按顺序执行。

Executors.java 源代码的摘录,

public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>(),
                                threadFactory));
}

第二个参数ThreadPoolExecutor是最大线程池大小。newSingleThreadExecutor此参数使用 1,这保证您一次最多使用一个线程。

于 2014-01-22T11:53:21.517 回答