Java 如何将不同类的三个线程同步在一起

Java 如何将不同类的三个线程同步在一起,java,multithreading,synchronization,Java,Multithreading,Synchronization,我有三个线程,我需要同步三个线程, 我从用户处获取n,直到需要计数器时,并增加counterOne直到n 值(使用ThreadOne)如果counterOne是25的倍数,我需要增加值 当counterTwo是4的倍数时,则i 需要将计数器三增加1(通过使用ThreadThree),并需要打印值 n=计数器1值后的计数器1、计数器2和计数器3 我已经实现了这个,这是代码,但是counter2和counter1的值没有增加。 我做错了什么 测试用例 输入:30 输出:计数器一:30,计数器二:0计

我有三个线程,我需要同步三个线程, 我从用户处获取n,直到需要计数器时,并增加counterOne直到n 值(使用ThreadOne)如果counterOne是25的倍数,我需要增加值 当counterTwo是4的倍数时,则i 需要将计数器三增加1(通过使用ThreadThree),并需要打印值 n=计数器1值后的计数器1、计数器2和计数器3

我已经实现了这个,这是代码,但是counter2和counter1的值没有增加。 我做错了什么

测试用例

输入:30

输出:计数器一:30,计数器二:0计数器三:0

计数器1将一个接一个地增加,当遇到25倍时,计数器2应增加2倍,当添加4倍时,计数器3应增加1。

但是当25来的时候,在counterOne中加1时,它应该将counter2增加2,但它没有增加,当counterOne增加到304,8,12,16,20,24,28时,这些都是4的倍数,所以counter3应该是7,但它也是零

输出应为:计数器一:30,计数器二:1计数器三:7

代码如下:

计数器类

  public class Counter {
        int counterOne;
        int counterTwo;
        int counterThree;
        int flag = 0;
    }
 import java.util.Scanner;
        class Main {
        public static void main(String args[]) {
            Scanner in = new Scanner(System.in);
            int n = in.nextInt();
    
            Counter count = new Counter();

        ThreadOne objOne = new ThreadOne(count, n);
        Thread one = new Thread(objOne);

        ThreadTwo objTwo = new ThreadTwo(count);
        Thread two = new Thread(objTwo);

        ThreadThree objThree = new ThreadThree(count);
        Thread three = new Thread(objThree);

        try {
            one.start();
            two.start();
            three.start();

        } catch (Exception e) {
            e.printStackTrace();
        }
        in.close();
    }
}
 class ThreadOne implements Runnable {
        Counter count;
        int n;
    
        public ThreadOne(Counter count, int n) {
            this.count = count;
            this.n = n;
        }
         @Override
        public synchronized void run() {
               while (count.counterOne != n) {
                     count.counterOne += 1;
                   }
                  if (count.counterOne == n) {
                count.flag = 1;
                System.out.print(count.counterOne + " " + count.counterTwo + " " + count.counterThree);
            }
         }
      }
class ThreadTwo implements Runnable {
    Counter count;
    public ThreadTwo(Counter count) {
        this.count = count;
    }
    @Override
    public synchronized void run() {
        while (count.flag != 1) {
            if (count.counterOne % 25 == 0) {
                count.counterTwo += 2;
            }
        }
    }
}
class ThreadThree implements Runnable {
    Counter count;
    public ThreadThree(Counter count) {
        this.count = count;
    }
    @Override
    public synchronized void run() {
        while (count.flag != 1) {
            if (count.counterTwo % 4 == 0) {
                count.counterThree += 1;
            }
        }
    }

}
主类

  public class Counter {
        int counterOne;
        int counterTwo;
        int counterThree;
        int flag = 0;
    }
 import java.util.Scanner;
        class Main {
        public static void main(String args[]) {
            Scanner in = new Scanner(System.in);
            int n = in.nextInt();
    
            Counter count = new Counter();

        ThreadOne objOne = new ThreadOne(count, n);
        Thread one = new Thread(objOne);

        ThreadTwo objTwo = new ThreadTwo(count);
        Thread two = new Thread(objTwo);

        ThreadThree objThree = new ThreadThree(count);
        Thread three = new Thread(objThree);

        try {
            one.start();
            two.start();
            three.start();

        } catch (Exception e) {
            e.printStackTrace();
        }
        in.close();
    }
}
 class ThreadOne implements Runnable {
        Counter count;
        int n;
    
        public ThreadOne(Counter count, int n) {
            this.count = count;
            this.n = n;
        }
         @Override
        public synchronized void run() {
               while (count.counterOne != n) {
                     count.counterOne += 1;
                   }
                  if (count.counterOne == n) {
                count.flag = 1;
                System.out.print(count.counterOne + " " + count.counterTwo + " " + count.counterThree);
            }
         }
      }
class ThreadTwo implements Runnable {
    Counter count;
    public ThreadTwo(Counter count) {
        this.count = count;
    }
    @Override
    public synchronized void run() {
        while (count.flag != 1) {
            if (count.counterOne % 25 == 0) {
                count.counterTwo += 2;
            }
        }
    }
}
class ThreadThree implements Runnable {
    Counter count;
    public ThreadThree(Counter count) {
        this.count = count;
    }
    @Override
    public synchronized void run() {
        while (count.flag != 1) {
            if (count.counterTwo % 4 == 0) {
                count.counterThree += 1;
            }
        }
    }

}
ThreadOne类

  public class Counter {
        int counterOne;
        int counterTwo;
        int counterThree;
        int flag = 0;
    }
 import java.util.Scanner;
        class Main {
        public static void main(String args[]) {
            Scanner in = new Scanner(System.in);
            int n = in.nextInt();
    
            Counter count = new Counter();

        ThreadOne objOne = new ThreadOne(count, n);
        Thread one = new Thread(objOne);

        ThreadTwo objTwo = new ThreadTwo(count);
        Thread two = new Thread(objTwo);

        ThreadThree objThree = new ThreadThree(count);
        Thread three = new Thread(objThree);

        try {
            one.start();
            two.start();
            three.start();

        } catch (Exception e) {
            e.printStackTrace();
        }
        in.close();
    }
}
 class ThreadOne implements Runnable {
        Counter count;
        int n;
    
        public ThreadOne(Counter count, int n) {
            this.count = count;
            this.n = n;
        }
         @Override
        public synchronized void run() {
               while (count.counterOne != n) {
                     count.counterOne += 1;
                   }
                  if (count.counterOne == n) {
                count.flag = 1;
                System.out.print(count.counterOne + " " + count.counterTwo + " " + count.counterThree);
            }
         }
      }
class ThreadTwo implements Runnable {
    Counter count;
    public ThreadTwo(Counter count) {
        this.count = count;
    }
    @Override
    public synchronized void run() {
        while (count.flag != 1) {
            if (count.counterOne % 25 == 0) {
                count.counterTwo += 2;
            }
        }
    }
}
class ThreadThree implements Runnable {
    Counter count;
    public ThreadThree(Counter count) {
        this.count = count;
    }
    @Override
    public synchronized void run() {
        while (count.flag != 1) {
            if (count.counterTwo % 4 == 0) {
                count.counterThree += 1;
            }
        }
    }

}
ThreadTwo class

  public class Counter {
        int counterOne;
        int counterTwo;
        int counterThree;
        int flag = 0;
    }
 import java.util.Scanner;
        class Main {
        public static void main(String args[]) {
            Scanner in = new Scanner(System.in);
            int n = in.nextInt();
    
            Counter count = new Counter();

        ThreadOne objOne = new ThreadOne(count, n);
        Thread one = new Thread(objOne);

        ThreadTwo objTwo = new ThreadTwo(count);
        Thread two = new Thread(objTwo);

        ThreadThree objThree = new ThreadThree(count);
        Thread three = new Thread(objThree);

        try {
            one.start();
            two.start();
            three.start();

        } catch (Exception e) {
            e.printStackTrace();
        }
        in.close();
    }
}
 class ThreadOne implements Runnable {
        Counter count;
        int n;
    
        public ThreadOne(Counter count, int n) {
            this.count = count;
            this.n = n;
        }
         @Override
        public synchronized void run() {
               while (count.counterOne != n) {
                     count.counterOne += 1;
                   }
                  if (count.counterOne == n) {
                count.flag = 1;
                System.out.print(count.counterOne + " " + count.counterTwo + " " + count.counterThree);
            }
         }
      }
class ThreadTwo implements Runnable {
    Counter count;
    public ThreadTwo(Counter count) {
        this.count = count;
    }
    @Override
    public synchronized void run() {
        while (count.flag != 1) {
            if (count.counterOne % 25 == 0) {
                count.counterTwo += 2;
            }
        }
    }
}
class ThreadThree implements Runnable {
    Counter count;
    public ThreadThree(Counter count) {
        this.count = count;
    }
    @Override
    public synchronized void run() {
        while (count.flag != 1) {
            if (count.counterTwo % 4 == 0) {
                count.counterThree += 1;
            }
        }
    }

}
螺纹三级

  public class Counter {
        int counterOne;
        int counterTwo;
        int counterThree;
        int flag = 0;
    }
 import java.util.Scanner;
        class Main {
        public static void main(String args[]) {
            Scanner in = new Scanner(System.in);
            int n = in.nextInt();
    
            Counter count = new Counter();

        ThreadOne objOne = new ThreadOne(count, n);
        Thread one = new Thread(objOne);

        ThreadTwo objTwo = new ThreadTwo(count);
        Thread two = new Thread(objTwo);

        ThreadThree objThree = new ThreadThree(count);
        Thread three = new Thread(objThree);

        try {
            one.start();
            two.start();
            three.start();

        } catch (Exception e) {
            e.printStackTrace();
        }
        in.close();
    }
}
 class ThreadOne implements Runnable {
        Counter count;
        int n;
    
        public ThreadOne(Counter count, int n) {
            this.count = count;
            this.n = n;
        }
         @Override
        public synchronized void run() {
               while (count.counterOne != n) {
                     count.counterOne += 1;
                   }
                  if (count.counterOne == n) {
                count.flag = 1;
                System.out.print(count.counterOne + " " + count.counterTwo + " " + count.counterThree);
            }
         }
      }
class ThreadTwo implements Runnable {
    Counter count;
    public ThreadTwo(Counter count) {
        this.count = count;
    }
    @Override
    public synchronized void run() {
        while (count.flag != 1) {
            if (count.counterOne % 25 == 0) {
                count.counterTwo += 2;
            }
        }
    }
}
class ThreadThree implements Runnable {
    Counter count;
    public ThreadThree(Counter count) {
        this.count = count;
    }
    @Override
    public synchronized void run() {
        while (count.flag != 1) {
            if (count.counterTwo % 4 == 0) {
                count.counterThree += 1;
            }
        }
    }

}

这里有几个问题:

第一点是
synchronized
仅在线程运行相同的代码块时才起作用。因此,当每个线程中有一个单独的同步块时,它们不会相互锁定。可以将对象设置为锁定,只要所有块都引用同一个对象作为锁定,该操作就会起作用

第二,线程1可能在其他两个线程开始之前完成。所以他们没有机会建立一个锁。这就是为什么你会得到全零

第三,你的循环做的太少了,以至于它们重复了很多次而没有释放锁。所以你真的需要一个
sleep()

第4点是,假设每个线程将整齐地一次一个地排队。你不能这样假设。实际上,一些线程可以在任何其他特定线程进入之前运行多次。如果发生这种情况,你的计数就会乱了

第五,代码中有几个简单的bug,这会使它无法工作。例如,线程3将线程2计数器除以4,而不是线程1计数器。所以当N小于50时,计数器3不可能是非零的

但第四个问题是需要解决的最大问题。您不能线性思考,因此必须假设每个线程中循环的每次执行在其逻辑中都是完全独立的。换句话说,您不能假设其他两个线程在每次循环执行之间都只运行一次。编写的代码显然有这样的假设,当我让它运行所有线程时,它给出了完全疯狂的数字

我在
计数器中引入了两个新字段
lastCheckedByTwo
lastCheckedByThree
。我还将integer标志字段更改为boolean,并将其命名为更有意义的名称
continueCounting
。不要将整数用作布尔值

现在,更改了其中的循环,因此当
ThreadOne
ThreadThree
都完成了模逻辑时,
ThreadOne
只会增加
counterOne
。第二个两个线程在完成任务后更新
lastchedbytwo
lastchedbythree
。而且他们每增加一次
计数器
,只做一次自己的事情

基本上这意味着
计数器
现在拥有进程的完整状态,各个线程在工作时更新它,并检查它以确保它们应该做任何事情

我将synchronized块作为Main的一个静态方法移动,它接受来自调用方法的runnable,调用方法位于各种线程类中。为了更容易地查看调用了哪些线程以及调用了多少次,我给出了线程的名称,并在方法中加入了
System.out.println()
调用

您可以在
updateCounter()
方法中处理
sleep()
。如果将其设置得很低,您将看到整个系统将开始振荡,并且需要很长时间才能完成来自同一线程的数千个背靠背调用。30毫秒似乎是个不错的数字

class Main {
    static Counter count = new Counter();
    static int loopCounter = 0;

    public static void main(String args[]) {
        System.out.println("How Much? ");
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();

        try {
            new Thread(new ThreadOne(count, n), "Thread 1").start();
            new Thread(new ThreadTwo(count), "Thread 2").start();
            new Thread(new ThreadThree(count), "Thread 3").start();
        } catch (Exception e) {
            e.printStackTrace();
        }
        in.close();
    }

    public synchronized static void updateCounter(Runnable updater) {
        updater.run();
        try {
            Thread.sleep(30);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(++loopCounter + "   " + Thread.currentThread()
                                                         .getName() + " -> One: " + count.counterOne + " Two: " + count.counterTwo + " " + "Three:" + " " + count.counterThree);
    }
}


class ThreadOne implements Runnable {
    Counter count;
    int n;

    public ThreadOne(Counter count, int n) {
        this.count = count;
        this.n = n;
    }

    @Override
    public void run() {
        while (count.continueCounting) {
            Main.updateCounter(() -> {
                if ((count.lastCheckedByTwo == count.counterOne) && (count.lastCheckedByThree == count.counterOne)) {
                    count.counterOne += 1;
                    if (count.counterOne == n) {
                        count.continueCounting = false;
                        System.out.println(count.counterOne + " " + count.counterTwo + " " + count.counterThree);
                    }
                }
            });
        }
    }
}


class ThreadTwo implements Runnable {
    Counter count;

    public ThreadTwo(Counter count) {
        this.count = count;
    }

    @Override
    public void run() {
        while (count.continueCounting) {
            Main.updateCounter(() -> {
                if (count.lastCheckedByTwo != count.counterOne) {
                    count.lastCheckedByTwo = count.counterOne;
                    if (count.counterOne % 25 == 0) {
                        count.counterTwo += 2;
                    }
                }
            });
        }
    }
}


class ThreadThree implements Runnable {
    Counter count;

    public ThreadThree(Counter count) {
        this.count = count;
    }

    @Override
    public synchronized void run() {
        while (count.continueCounting) {
            Main.updateCounter(() -> {
                if (count.lastCheckedByThree != count.counterOne) {
                    count.lastCheckedByThree = count.counterOne;
                    if (count.counterOne % 4 == 0) {
                        count.counterThree += 1;
                    }
                }
            });
        }
    }
}


public class Counter {
    int counterOne = 0;
    int counterTwo = 0;
    int counterThree = 0;
    int lastCheckedByTwo = 0;
    int lastCheckedByThree = 0;
    boolean continueCounting = true;
}

这里有几个问题:

第一点是
synchronized
仅在线程运行相同的代码块时才起作用。因此,当每个线程中有一个单独的同步块时,它们不会相互锁定。可以将对象设置为锁定,只要所有块都引用同一个对象作为锁定,该操作就会起作用

第二,线程1可能在其他两个线程开始之前完成。所以他们没有机会建立一个锁。这就是为什么你会得到全零

第三,你的循环做的太少了,以至于它们重复了很多次而没有释放锁。所以你真的需要一个
sleep()

第4点是,假设每个线程将整齐地一次一个地排队。你不能这样假设。事实上,一些