此问题的完整代码可在此处获得:https://github.com/NACHC-CAD/thread-tool
下面显示的代码似乎一直运行到完成,但从未逃脱此处显示的while循环。
while (this.active.size() > 0) {
// System.out.println("here");
}
如果我取消注释//系统。出来println(“此处”)
它确实运行到完成。如果我加上一秒钟的睡眠,它也会运行到完成。
更大的问题是,如果我尝试在实际应用程序中使用此代码,代码会运行一段时间,然后似乎死锁(即代码只是停止运行)。
我需要做什么来解决这个问题?
package org.nachc.tools.threadtool;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.nachc.tools.threadtool.runnableiter.ThreadToolUser;
import org.nachc.tools.threadtool.worker.ThreadToolWorker;
import org.nachc.tools.threadtool.worker.ThreadToolWorkerRunnable;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ThreadRunner {
private int numberOfThreadsPerWorker;
private int numberOfRunnablesPerWorker;
private int numberOfWorkers;
private ThreadToolUser runnableIter;
private List<ThreadToolWorker> active = new ArrayList<ThreadToolWorker>();
private Object lock = new Object();
private ThreadPoolExecutor executor;
public ThreadRunner(int numberOfThreadsPerWorker, int numberOfRunnablesPerWorker, int numberOfWorkers, ThreadToolUser runnableIter) {
this.numberOfThreadsPerWorker = numberOfThreadsPerWorker;
this.numberOfRunnablesPerWorker = numberOfRunnablesPerWorker;
this.numberOfWorkers = numberOfWorkers;
this.runnableIter = runnableIter;
this.executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(numberOfWorkers);
}
public void exec() {
synchronized (lock) {
addWorkers();
}
while (this.active.size() > 0) {
// System.out.println("here");
}
log.info("SHUTTING DOWN----------------");
executor.shutdown();
try {
executor.awaitTermination(1000, TimeUnit.HOURS);
} catch (Exception exp) {
throw (new RuntimeException(exp));
}
}
private void addWorkers() {
log.info("start addWorkers");
while (runnableIter.hasNext() && active.size() < numberOfWorkers) {
ThreadToolWorker worker = getNextWorker();
if (worker == null) {
break;
} else {
this.active.add(worker);
}
}
log.info("done addWorkers");
}
private ThreadToolWorker getNextWorker() {
synchronized (lock) {
log.info("start next worker");
if (runnableIter.hasNext() == false) {
return null;
}
List<Runnable> runnableList = new ArrayList<Runnable>();
while (runnableList.size() < numberOfRunnablesPerWorker && runnableIter.hasNext()) {
runnableList.add(runnableIter.getNext());
}
ThreadToolWorker worker = new ThreadToolWorker(runnableList, numberOfThreadsPerWorker, this);
ThreadToolWorkerRunnable runnable = new ThreadToolWorkerRunnable(worker);
this.executor.execute(runnable);
log.info("done next worker");
return worker;
}
}
public void done(ThreadToolWorker worker) {
synchronized (lock) {
log.info("start done");
this.active.remove(worker);
if (active.size() > 0) {
addWorkers();
}
log.info("done done");
}
}
public void logActive() {
synchronized (lock) {
log.info("------------");
log.info("active: " + active.size());
log.info("waiting: " + runnableIter.waiting());
log.info("------------");
}
}
}
您的循环访问this.active.size()
而没有任何同步。Java的内存可见性规则不保证当(如果有的话)一个查看共享变量的线程将看到其他线程所做的更改,如果正在查找的线程不使用某种形式的同步与其他线程。
如果要轮询活动列表的状态,请考虑执行以下操作:
while (true) {
synchronized(lock) {
if (this.active.size() <= 0) break;
}
try {
Thread.sleep(1000);
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}
sleep()
调用为其他线程提供了运行的机会。如果没有睡眠,运行这个循环的线程将使用100%的CPU,这可能对应用程序的性能有害。
但有比投票更好的选择。您可以等待
活动
列表变为空。
synchronized(lock) {
while (this.active.size() > 0) {
lock.wait();
}
}
wait()
调用暂时释放锁
,然后等待另一个线程通知()
锁,最后在返回前重新锁定锁:
public void done(ThreadToolWorker worker) {
synchronized (lock) {
log.info("start done");
this.active.remove(worker);
if (active.size() > 0) {
addWorkers();
}
else {
lock.notifyAll();
}
log.info("done done");
}
}
在执行程序时,为了提供性能,处理器和编译器常常会对指令进行重排序,但是不能随意重排序,不是你想怎么排序就怎么排序,它需要满足以下两个条件: 在单线程环境下不能改变程序运行的结果; 存在数据依赖关系的不允许重排序 需要注意的是:重排序不会影响单线程环境的执行结果,但是会破坏多线程的执行语义。
我正在http://www.python-course.eu/threads.php的帮助下学习python线程处理。这段代码的解释让我很困惑: 代码: 读取num_thread的值 一个新的int实例将增加或减少1(我认为一个新的int对象将被创建) 将新值分配给num_threads 像这样的错误发生在增量赋值的情况下: 第一个线程读取变量num_threads,它的值仍然是0。令人困惑的是:
主要内容:1 什么是Java多线程,2 Java多线程的优点,3 进程与线程区别,4 Java Thread类,5 Java Thread类的方法1 什么是Java多线程 Java 多线程指的是同时执行多个线程的处理。 线程是轻量级子进程,是最小的处理单元。多处理和多线程都用于实现多任务。 但是,我们使用多线程而不是多进程,因为线程使用共享内存区域。它们不分配单独的内存区域,因此节省了内存,并且线程之间的上下文切换比进程花费的时间更少。 线程是轻量级子进程,是最小的处理单元。这是一条单独的执行路
问题内容: 为什么在调用execute方法时将未处理的异常重新抛出在worker中?结果,将在下一次执行时创建新线程,以最大化线程数 问题答案: 为什么当RuntimeException发生时,java ThreadPoolExecutor杀死线程? 我只能猜测, 直接进行线程调用而不将其包装在a中的原因是,这样,即使您不在乎结果,也不会招致该线程的开销。 __ 如果您的线程抛出,这是很罕见的事情
我试图通过拆分列表来检查元素是否在字符串中: `公共类ParallelSearchComment扩展了RecursiveTask{private static final long serialVersionUID=1L; `
死锁描述了另外两个线程因为永远等待对方而被阻塞的情况。当死锁发生时,程序永远挂起,你唯一能做的就是杀死程序。 为什么在下面给出的示例生产者-消费者问题中没有发生死锁: 我想知道为什么当同步对象正在等待其他线程释放锁时,在同步块中调用等待方法不会导致死锁?