同步关键字Java速度效率
如果我错了,请随时纠正我强> java中的synchronized关键字使方法无法在不同线程之间同时运行。在我的程序中,我有4个不同的线程在同一时间运行,计数为100.000 将synchronized关键字添加到正在执行的方法时,所需的时间应该是多线程的四倍 无论以哪种方式执行程序,大约需要16秒 这是我的密码同步关键字Java速度效率,java,multithreading,performance,Java,Multithreading,Performance,如果我错了,请随时纠正我 java中的synchronized关键字使方法无法在不同线程之间同时运行。在我的程序中,我有4个不同的线程在同一时间运行,计数为100.000 将synchronized关键字添加到正在执行的方法时,所需的时间应该是多线程的四倍 无论以哪种方式执行程序,大约需要16秒 这是我的密码 public class ExerciseThree { public static void main(String[] args) { Even even =
public class ExerciseThree {
public static void main(String[] args) {
Even even = new Even();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
System.out.println(even.next());
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
System.out.println(even.next());
}
});
Thread t3 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
System.out.println(even.next());
}
});
Thread t4 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
System.out.println(even.next());
}
});
System.out.println("starting thread 1");
t1.start();
System.out.println("starting thread 2");
t2.start();
System.out.println("starting thread 3");
t3.start();
System.out.println("starting thread 4");
t4.start();
}
}
由于
println
比计算要昂贵得多,这一切都是关于它的并发执行。但是,println
本身是同步的,因此不能加速
没有它,只做
public int next() {
n++;
n++;
return n;
}
受到许多优化的影响。特别是双增量可以替换为n+=2
,并且由于没有使用返回值,因此返回被消除。环状
for (int i = 0; i < 100000; i++) {
even.next());
}
for(int i=0;i<100000;i++){
偶数;
}
可以减少到仅n+=200000
Benchn标记通常很难,尤其是在Java中。无论如何,请使用JMH,它可以解决大多数问题。由于
println
比计算要昂贵得多,所以它都是关于并发执行的。但是,println
本身是同步的,因此不能加速
没有它,只做
public int next() {
n++;
n++;
return n;
}
受到许多优化的影响。特别是双增量可以替换为n+=2
,并且由于没有使用返回值,因此返回被消除。环状
for (int i = 0; i < 100000; i++) {
even.next());
}
for(int i=0;i<100000;i++){
偶数;
}
可以减少到仅n+=200000
Benchn标记通常很难,尤其是在Java中。无论如何,请使用JMH,它可以解决大多数问题。正如评论部分已经指出的,微基准标记是一个复杂的问题,因为许多因素会影响执行时间(例如,即时编译和垃圾收集)。评论部分已经提供了一个很好的答案,但我建议您也看看我的答案,类似的问题链接到一个by,它很好地介绍了微基准营销以及需要注意的事项 已经提到,
println()
在这样的微基准中没有位置。此外,我想指出,您应该使用某种同步机制(例如,倒计时闩锁
)来确保四个线程同时开始执行它们的工作。创建和启动线程所涉及的开销可能会导致较早的线程在较后的线程启动所需的时间内开始其工作,从而导致对甚至锁的争用比您预期的要少。例如,这可能看起来像这样:
public class ExerciseThree {
public static void main(String[] args) {
final CountDownLatch startSignal = new CountDownLatch(1);
final CountDownLatch threadReadyCheck = new CountDownLatch(4);
final CountDownLatch threadDoneCheck = new CountDownLatch(4);
Even even = new Even();
Thread t1 = new Thread(() -> {
threadReadyCheck.countDown();
startSignal.await();
for (int i = 0; i < 100000; i++) {
even.next();
}
threadDoneCheck.countDown();
});
Thread t2 = new Thread(() -> {
threadReadyCheck.countDown();
startSignal.await();
for (int i = 0; i < 100000; i++) {
even.next();
}
threadDoneCheck.countDown();
});
Thread t3 = new Thread(() -> {
threadReadyCheck.countDown();
startSignal.await();
for (int i = 0; i < 100000; i++) {
even.next();
}
threadDoneCheck.countDown();
});
Thread t4 = new Thread(() -> {
threadReadyCheck.countDown();
startSignal.await();
for (int i = 0; i < 100000; i++) {
even.next();
}
threadDoneCheck.countDown();
});
t1.start();
t2.start();
t3.start();
t4.start();
// Wait until all threads are ready to perform their work.
threadReadyCheck.await();
// All threads ready.
// This is where you log start time.
long start = System.nanoTime();
// Let threads progress to perform their actual work.
startSignal.countDown();
// Wait for threads to finish their work.
threadDoneCheck.await();
long end = System.nanoTime();
// Note that this is again subject to many factors, for example when the main thread gets scheduled again after the workers terminate.
long executionTime = end - start;
}
}
公共课练习三{
公共静态void main(字符串[]args){
最终倒计时闩锁启动信号=新倒计时闩锁(1);
最终倒计时闩锁threadReadyCheck=新倒计时闩锁(4);
最终倒计时闩锁螺纹Donecheck=新倒计时闩锁(4);
偶数=新偶数();
线程t1=新线程(()->{
threadReadyCheck.countDown();
开始信号。等待();
对于(int i=0;i<100000;i++){
偶数;
}
threadDoneCheck.countDown();
});
线程t2=新线程(()->{
threadReadyCheck.countDown();
开始信号。等待();
对于(int i=0;i<100000;i++){
偶数;
}
threadDoneCheck.countDown();
});
线程t3=新线程(()->{
threadReadyCheck.countDown();
开始信号。等待();
对于(int i=0;i<100000;i++){
偶数;
}
threadDoneCheck.countDown();
});
线程t4=新线程(()->{
threadReadyCheck.countDown();
开始信号。等待();
对于(int i=0;i<100000;i++){
偶数;
}
threadDoneCheck.countDown();
});
t1.start();
t2.start();
t3.start();
t4.开始();
//等待所有线程准备好执行其工作。
threadReadyCheck.await();
//所有线程都准备好了。
//这是记录开始时间的地方。
长启动=System.nanoTime();
//让线程继续执行其实际工作。
开始信号倒计时();
//等待线程完成其工作。
threadDoneCheck.await();
long end=System.nanoTime();
//请注意,这同样受到许多因素的影响,例如,当工作线程终止后主线程再次被调度时。
长执行时间=结束-开始;
}
}
正如评论部分已经指出的,微基准标记是一个复杂的问题,因为许多因素会影响执行时间(例如,即时编译和垃圾收集)。评论部分已经提供了一个很好的答案,但我建议您也看看我的答案,类似的问题链接到一个by,它很好地介绍了微基准营销以及需要注意的事项
已经提到,println()
在这样的微基准中没有位置。此外,我想指出,您应该使用某种同步机制(例如,倒计时闩锁
)来确保四个线程同时开始执行它们的工作。创建和启动线程所涉及的开销可能会导致较早的线程在较后的线程启动所需的时间内开始其工作,从而创建较少的con