我想为我的一个项目测试多线程,试图开发一个解决方案,以防出现问题。
所以我做了一个小测试:
public class main
{
static int addToCounter;
static int addToErrorCounter;
public static void main(String[] args) throws InterruptedException
{
int threads = 10;
Executor exec = new Executor();
for (int i = 0; i < threads; i++)
{
double error = Math.random();
testClass aldo = new testClass();
Thread thread = aldo.getThread(300, error);
exec.execute(thread);
}
while (threads != (addToCounter + addToErrorCounter))
{
System.out.println("Not all threads finished, number of finished threads is: " + (addToCounter + addToErrorCounter));
Thread.sleep(50);
}
System.out.println("Number of Threads that finished correctly: " + addToCounter);
}
}
import test1.main;
public class testClass
{
public Thread getThread(long time, double error)
{
Thread thread = new Thread()
{
public void run()
{
try
{
Thread.sleep(time);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
if (error > 0.5)
{
main.addToErrorCounter++;
throw new java.lang.Error("HELLO");
}
System.out.println("I DID THIS!");
main.addToCounter++;
}
};
return thread;
}
}
(您必须修复导入,我还使用自定义类Executor
,尽管这只是ExecutorService
的包装)
奇怪的是,有时它工作正常,有时则不正常(终止线程总数为9,尽管我可以清楚地看到它打印了“我做到了!”误差正好是10倍)。
任何修复?
我猜后缀操作符(main.addToCounter
)不是原子的。这行代码可能相当于:
int temp = main.addToCounter;
main.addToCounter = temp + 1;
return temp;
当多个线程同时执行此操作时,两个线程可能会获得相同的temp
值(因为两个线程都在执行第二个线程之前形成上述伪代码的第一行),因此一旦所有线程完成,计数器总数将太小。明白为什么我不是原子吗?了解更多信息。
这种情况下的一个快速修复方法是将addToCounter
设置为原子整数,然后使用addToCounter。incrementAndGet()
代替addToCounter
。
问题可能是赛车状态。“”运算符不是原子运算符。想象一下下面的场景。同时有两条线。两人都想增加一个数字并完成。该数字的初始值为0。线程0读取数字,现在知道它是0。线程1读取数字,现在知道它是0。线程0(知道它是0)现在将1写入内存。线程1不知道这个数字已经改变了,并且仍然相信这个数字是0,所以他还将1写入内存。
你需要一个同步机制,一个锁,一个信号灯或其他东西。
有关更多信息,请查看以下内容:http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/
对于您的示例,您可以使用该链接中的“synchronized”示例。
向主类添加一个如下所示的方法,以增加addToCounter
,并向addToErrorCounter
添加一个方法,以消除错误计数器的影响:
synchronized AddToError(int e){
addToError += e;
}
synchronized IncCounter(){
addToCounter++;
}
问题内容: 我使用Hibernate创建了一个程序。 程序到达主要功能端,但是程序正在运行。 我不知道使用Hibernate 4.x版进行配置时是否会发生这种情况。 配置方式错误吗? manual1_1_first_hibernate_apps.java 实用程序 程序终止并使用buildSessionFactory方法时,以下控制台日志片段。 但是,如果不使用已弃用的buildSessionFa
问题内容: 我找到了终止(关闭或停止)Java程序的方法。我找到了两个解决方案。 使用 return; 当我想退出或终止程序执行时,添加它。 使用 System.exit() ; 有时我用它。我从This Question中了解了 Sytem.exit()。 所以,我对他们都了解一点。但是我仍然对它们的实际工作方式感到困惑。请检查以下代码… 我确定 2不会出现。我想知道为什么或其他代码可以在的语句
在linux中,当主线程终止时,整个过程都会退出,不管它是以何种方式终止的,都是通过函数out()或从main返回。如果主线程从main()返回,它将返回到称为crt. o或类似的“C运行时”。在crt. o中,它的c代码是这样的:退出(main(argc, argv));退出()将由主线程 最终调用,结果,所有线程都终止。 我的想法正确吗? 如果在crt中。o exit()被诸如void thr
问题内容: 如何使多线程python程序响应Ctrl + C键事件? 编辑: 代码是这样的: 我试图在所有线程上删除join(),但仍然无法正常工作。是否因为每个线程的run()过程中的锁段? 编辑: 上面的代码应该可以工作,但是当当前变量在5,000-6,000范围内并遍历以下错误时,它总是会中断 问题答案: 在启动主线程之前,将除主线程之外的每个线程都设为守护进程(在2.6或更高版本中,在2.
我尝试构建一个GUI应用程序,从相机抓取帧并在Tkinter GUI中显示它们。Tkinter mainloop在主线程中执行,而gui的帧抓取和更新在单独的线程中进行。 下面的代码作为一个视频流被抓取并正确显示在我的gui窗口中。但是,当我通过单击“x”来调用on_close()方法来关闭gui时,gui将关闭,但程序不会完全终止。最后一次CLI输出将为“Mainloop stopped!”,但
问题内容: 这似乎是一个是或否的问题,我希望可以在某个地方回答它,但我当然找不到。Java中的内存泄漏发生的频率不如使用C或C ++这样的语言开发时发生的频率高,但是它们可以发生。 除某些情况(如共享内存)外,大多数操作系统都会清除程序终止时分配的内存。当JVM退出时,这仍然适用吗?如果我无意间在Java中创建了内存泄漏,JVM,Linux或Windows OS都可以解决吗? 问题答案: 是的,J