同步对象上的java多线程性能

kb5ga3dv  于 2021-07-03  发布在  Java
关注(0)|答案(2)|浏览(341)

我正在尝试测试同步对象的多线程性能。但是,对于1个线程或16个线程,执行时间是相同的。
剩下的代码在这里。https://codeshare.io/5oj6ng

public void run() {
        start = new Date().getTime();
        System.out.println(start);

            while (threadlist.size() < 9000) { //16 or more

                  //  try{Thread.sleep(100);}catch (Exception f){}

                Thread t = new Thread(new Runnable() {

                    public void run() {
                        while (add(1,3) < 1000000);
                        end = new Date().getTime();
                        System.out.println((end-start));
                    }
                });
                    threadlist.add(t);

               while( threadlist.iterator().hasNext()){
                   threadlist.iterator().next().start();
                   try{threadlist.iterator().next().join();}catch (Exception a){}
               }
            }

    }
gzjq41n4

gzjq41n41#

你的代码有一些问题。第一:

public void run() {
       while (true) {
            add(1, 3);
        }
 }

这些线程从未停止工作,我建议重写您的逻辑:

public void (run) {
        while(add(1,3) < 1000000);
        System.out.println("now 1000000");
   }

   public int add(int val1, int val2) {
        synchronized (this) {
            this.sum1 += val1;
            this.sum2 += val2;
            return this.sum1 + this.sum2;
            }
        }
    }

你启动线程,但从不调用 join ,最终你需要这样做。
您只创建了1个线程,而不是您想要的16个线程:

if (threadlist.size() < 1)

你想要什么

if (threadlist.size()  < 16)

最后,不要期望此代码有任何性能提升,因为您正在对象上同步:

synchronized (this){...}

所以基本上你的 add 方法是按顺序运行的,而不是并行运行的,因为线程将等待synchronized(this),并且只在synchronized语句 Package 的代码块中调用run-on。
试着通过添加 start = new Date().getTime(); 在平行区域之前,以及 end = new Date().getTime(); 之后。
您只需编写代码即可:

public void run() {
    start = new Date().getTime();
    System.out.println(start);
    while (threadlist.size() < 16) {
         Thread t = new Thread(() -> {
              while (add(1,3) < 1);
              System.out.println("now 1000000");
        });
        threadlist.add(t);
    }
    threadlist.forEach(Thread::start);

    threadlist.forEach(thr-> {
            try { thr.join();} 
            catch (InterruptedException e) { e.printStackTrace();}
     });
     end = new Date().getTime();
     System.out.println("Time taken : "+(end-start));

     public int add(int val1, int val2) {
            synchronized (this) {
                this.sum1 += val1;
                this.sum2 += val2;
                return this.sum1 + this.sum2;
                }
          }
      }
6vl6ewon

6vl6ewon2#

自从@dreamcrash回复后,您已经显著地更新了代码。
当前版本存在以下问题:

while( threadlist.iterator().hasNext()) {
   threadlist.iterator().next().start();
   try{threadlist.iterator().next().join();}catch (Exception a){}
 }

这将启动一个线程,然后将立即坐在周围,旋转它的拇指,直到该线程完成它的工作,然后将启动另一个线程。因此,一次活动线程不超过1个。 catch (Exception a){} 你在学习/调试,你这么做?哦,亲爱的。不要。永远不要写这样的块。更新ide或肌肉内存:正确的“我现在不想考虑异常”代码是 catch (Exception a) { throw new RuntimeException("Unhandled", a);} . 要说清楚,这不是问题所在,但这是一个非常坏的习惯,它需要被唤醒。 synchronized (this) { 我真的怀疑,如果你修复'加入'的问题,我前面提到这将永远运行更快。这个同步的调用很重要,但是它也会造成太多的阻塞,以至于您可能看不到任何实际的好处。
更一般地说,您试图加速的计算涉及一个累加器。
累加器是“并行化在这里是完全不可能的,它是无望的”的另一个词。
如果您想并行化算法,那么它不能包含累加器,这就是多线程(至少,如果多线程的目的是加快速度的话)正在做的事情。这个算法在线程中不能再快了。句号。
通常可以重写算法以停止依赖累加器。但这显然是一个看效果的练习,所以,找点别的,真的。在整个计算过程中不要只锁定一个对象:只有一个线程在实际工作,其他所有线程都在等待。

相关问题