加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java中的同步多线程

发布时间:2020-12-15 04:08:19 所属栏目:Java 来源:网络整理
导读:我是自学 Java,我想了解多线程.我创建了MyThread类,其作业执行循环直到条件为真,然后打印有关它的信息.它包含静态字段,它在构造函数中递增,在作业完成时递减.类标志是“告诉”线程何时开始. 不幸的是,当所有线程完成时,left不等于零.我使一些方法同步并且它
我是自学 Java,我想了解多线程.我创建了MyThread类,其作业执行循环直到条件为真,然后打印有关它的信息.它包含静态字段,它在构造函数中递增,在作业完成时递减.类标志是“告诉”线程何时开始.
不幸的是,当所有线程完成时,left不等于零.我使一些方法同步并且它变得更好但它仍然不完美.
我究竟做错了什么?

import java.util.Random;

class Flag
{
    private boolean ok = false;
    synchronized boolean ok()
    {
        return ok;
    }
    synchronized void setOk(boolean ok)
    {
        this.ok = ok;
    }
}

class MyThread extends Thread
{
    static int left = 0;

    synchronized void add()
    {
        left++;
    }

    synchronized int remove()
    {
        return --left;
    }

    String name;
    Flag flag;
    Random rnd = new Random();
    public MyThread(String name,Flag flag)
    {
        this.name = name;
        this.flag = flag;
        add();
    }

    public void run()
    {
        while(!flag.ok());

        double rnd;
        long count = 0;
        do{
            count++;
            rnd = Math.random();
        } while(rnd > 0.00001);
        print(count);
    }

    synchronized void print(long count)
    {
        System.out.printf("%s %10d left: %3d%n",name,count,remove());
    }
}

public class Test
{
    public static void main(String... args) throws Exception
    {
        Flag flag = new Flag();
        for(int i=0; i<2000; i++){
            new MyThread(String.format("%04d",i),flag).start();
        }

        flag.setOk(true);
    }
}

解决方法

left和–left不是原子操作.当几个线程试图执行时,可能是两个尝试同时向左递减的情况.此行为是由于您的代码在实例级别上同步(print是实例方法),而left是静态(类)变量.

另请注意,print()中打印的值是无序的(因为print不是静态同步的,因此打印的“last”值可能不是调用print的最后一个线程的值).

第一次更改:检查所有线程执行后左边确实为零.

public static void main(String... args) throws Exception
    {
        java.util.List<Thread> threads = new java.util.LinkedList<Thread>();
        Flag flag = new Flag();

        for(int i=0; i<20; i++){
            Thread thread=new MyThread(String.format("%04d",flag);
            threads.add(thread);
            thread.start();
        }

        flag.setOk(true);            
        for (Thread thread:threads) thread.join();
        System.out.println(MyThread.left);
    }

输出:

0003       9527 left:  19
0000      56748 left:  18
0006      11428 left:  17
0016     181845 left:   2
0010      95287 left:   3
0017     137911 left:   4
0018     432172 left:   5
0019     280280 left:   6
0013     421170 left:   7
0012     135830 left:   8
0015     104375 left:   9
0014     207409 left:  10
0001      16157 left:  11
0004     160136 left:  12
0008      31673 left:  13
0002      14589 left:  14
0005      23692 left:  15
0009      83419 left:  16
0011     231135 left:   0
0007     202603 left:   1
0

第二个更改:在类上进行同步(添加,删除和打印转换为静态方法;我们还要在运行中替换调用print,因为静态方法print中的名称不再可见).

synchronized static void add()
    {
        left++;
    }

  synchronized static int remove()
    {
        return --left;
    }

  synchronized static void print(long count,String name)
    {
        System.out.printf("%s %10d left: %3d%n",remove());
    }

  public void run()
    {
        ...
        print(count,name);
    }

输出:

0012      10207 left:  19
0006     121343 left:  18
0000      16236 left:  17
0008      81429 left:  16
0010      20250 left:  15
0002      14687 left:  14
0015      11051 left:  13
0017      23602 left:  12
0019      19651 left:  11
0005     180155 left:  10
0014     126578 left:   9
0003      41790 left:   8
0016      98362 left:   7
0001      96047 left:   6
0004     334071 left:   5
0009      46827 left:   4
0018     102826 left:   3
0013      71625 left:   2
0007     267208 left:   1
0011     188743 left:   0
0

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读