首页 文章

newSingleThreadExecutor和使用ThreadFactory时的顺序

提问于
浏览
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()));
       ........
    }

 }

2 回答

  • 0

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

    没有工厂的方法只会委托给一个 .

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

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

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

    保证您的代码按顺序执行,但不保证它始终是相同的线程 .

  • 2

    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作为此参数,这可以保证一次最多使用一个线程 .

相关问题