java - 自定义线程池 - 在不调用 start() 的情况下调用可运行
问题描述
我试图了解自定义线程池实现,如https://www.roytuts.com/custom-thread-pool-in-java/中所述。轮询出任务队列后
while ((r = taskQueue.poll()) != null) {
r.run();
}
代码直接调用run方法而不start()
先调用。所以,我有点困惑如何启动runnable而不在runnable上创建线程然后调用start方法?任何人都可以在我缺乏理解的地方消除我的困惑。谢谢
class CustomThreadPool {
// holds tasks
private BlockingQueue<Runnable> runnableQueue;
// holds the pool of worker threads
//private List<WorkerThread> threads;
// check if shutdown is initiated
private AtomicBoolean isThreadPoolShutDownInitiated;
public CustomThreadPool(final int noOfThreads) {
this.runnableQueue = new LinkedBlockingQueue<>();
//this.threads = new ArrayList<>(noOfThreads);
this.isThreadPoolShutDownInitiated = new AtomicBoolean(false);
// create worker threads
for (int i = 1; i <= noOfThreads; i++) {
WorkerThread thread = new WorkerThread(runnableQueue, this);
thread.setName("Worker Thread - " + i);
thread.start();
// threads.add(thread);
}
}
public void execute(Runnable r) throws InterruptedException {
if (!isThreadPoolShutDownInitiated.get()) {
runnableQueue.put(r);
} else {
throw new InterruptedException("Thread Pool shutdown is initiated, unable to execute task");
}
}
public void shutdown() {
isThreadPoolShutDownInitiated = new AtomicBoolean(true);
}
private class WorkerThread extends Thread {
// holds tasks
private BlockingQueue<Runnable> taskQueue;
// check if shutdown is initiated
private CustomThreadPool threadPool;
public WorkerThread(BlockingQueue<Runnable> taskQueue, CustomThreadPool threadPool) {
this.taskQueue = taskQueue;
this.threadPool = threadPool;
}
@Override
public void run() {
try {
// continue until all tasks finished processing
while (!threadPool.isThreadPoolShutDownInitiated.get() || !taskQueue.isEmpty()) {
Runnable r;
// Poll a runnable from the queue and execute it
while ((r = taskQueue.poll()) != null) {
r.run();
}
Thread.sleep(1);
}
} catch (RuntimeException | InterruptedException e) {
throw new CustomThreadPoolException(e);
}
}
}
private class CustomThreadPoolException extends RuntimeException {
private static final long serialVersionUID = 1L;
public CustomThreadPoolException(Throwable t) {
super(t);
}
}
}
public class ThreadPoolTest {
public static void main(String[] args) throws InterruptedException {
Runnable r = () -> {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " is executing task.");
} catch (InterruptedException e) {
e.printStackTrace();
}
};
CustomThreadPool threadPool = new CustomThreadPool(2);
threadPool.execute(r);
threadPool.execute(r);
threadPool.shutdown();
// threadPool.execute(r);
}
}
解决方案
您的线程池类调用thread.start()
哪个调用runnable.run()
调用thread.run()
. 最后一种方法是为使用 runnable 初始化的线程设计的,可以直接调用,也可以通过start()
.
根据Oracle 文档:start()
导致该线程开始执行;Java 虚拟机调用该线程的 run 方法。
编辑
调用runnable.run()
方法只是在当前线程(调用该方法的线程)上同步执行 runnable。在您的情况下,它是单独的(在 CustomThreadPool 中创建)。可以run()
直接调用 in main()
,会在主线程上同步执行runnable。通常,该示例不会破坏使用可运行对象的任何概念,因为它在单独的线程上执行它们。
长话短说:异步行为是通过在不同线程上执行可运行文件来实现的。在单个线程的范围内,调用多个runnablesrun()
会一个一个地同步执行。
推荐阅读
- swift - Swift:当前视图控制器在转换到下一个视图控制器期间重新显示
- python - How to add error handling with Python paramiko sftp on get filename with latest timestamp
- java - FileNotFoundException (Logback) while starting app
- python - 'No such file or directory' when I use python subprocess.run('docker build ...')
- node.js - Firebase 云功能 [错误:超出内存限制。函数调用被中断。] 在 youtube 视频上传
- .net - Web 服务器上禁用的 OPTIONS 标头(.NET Web API 和 Angular)
- c# - Problem with Automata simple conditional statements in C#
- c - Cannot follow tutorial (https://developer.gnome.org/anjuta-build-tutorial/stable/create-autotools.html.en)
- json - Swift 4 - 无法使用“(可编码)”类型的参数列表调用“编码”
- python - PYSPARK:CX_ORACLE.InterfaceError:不是查询