代码之家  ›  专栏  ›  技术社区  ›  Deen John

如何通过两个线程完成循环?比如说,通过ist线程从计数=1到计数=4,通过第二个线程从计数=5到8的循环?

  •  0
  • Deen John  · 技术社区  · 10 年前

    我希望输出的方式说明: 我想要两条线 高拉夫 厕所 完成while循环(从1到8),这样无论哪个线程开始,都会运行5次迭代(即,直到count=5),然后进入睡眠状态,然后下一个线程完成循环(运行count=6到count=8)。程序应该在那时结束。 对于这个场景,我创建了一个 实例变量计数 并在计数器方法中增加其值

    问题是:即使在同步计数器方法(计数器方法增加计数变量)之后,我也会得到一个奇怪的输出(输出附加在末尾)

    public class ThreadCounter implements Runnable {
       private int count; 
       @Override
       public void run(){
    
          try {
                counter(); // call synchronized counter function 
    
           } catch (InterruptedException e) {
            // TODO Auto-generated catch block
             e.printStackTrace();
             }
    
         }//end of run()
    
        public synchronized void counter() throws InterruptedException{
    
               while(true){
    
               // i want the loop to increment count from 1 to 4 by ist      thread(whichever thread runs ist) and then 5 to 8 by next thread
    
                     System.out.println("Which thread running ? " +Thread.currentThread().getName());
    
                     count++;
    
                     System.out.println("count is"+count);
    
                     if (count==5){
                 System.out.println("count is"+count +" and Thread is " +Thread.currentThread().getName());
                // when count is 5 make the current thread should  go to sleep
                   Thread.currentThread().sleep(7000);
                  }// if count==5 ends here
    
    
            //whichever thread starts now , should start the counter from count=5 
    
                 if (count==8){
                    break;
                // when count is 5 make the current thread go to sleep
    
                  }
    
              }// while loop ends here
       }// end of counter()
    }// end of class ThreadingIst
    
     public class ThreadTest {
    
        public static void main(String [] args){
    
            Thread t1= new Thread(new ThreadingIst());
    
            Thread t2= new Thread(new ThreadingIst());  
    
            t1.setName("John");
            t2.setName("Gaurav");
    
        t1.start();
        t2.start();
    
       }// main ends here
    
    }
    

    输出为:

    哪个线程正在运行?约翰 计数为1

    哪个线程正在运行?约翰 计数为2

    哪个线程正在运行?约翰 计数为3

    哪个线程正在运行?约翰 计数为4

    哪个线程正在运行?约翰 计数为5

    计数是5,线程约翰要睡觉了

    哪个线程正在运行?高拉夫 计数为1

    哪个线程正在运行?高拉夫 计数为2

    哪个线程正在运行?高拉夫 计数为3

    哪个线程正在运行?高拉夫 计数为4

    哪个线程正在运行?高拉夫 计数为5

    计数是5,Thread Gauravis要睡觉了

    哪个线程正在运行?高拉夫 计数为6

    哪个线程正在运行?高拉夫 计数为7

    哪个线程正在运行?高拉夫 计数为8

    计数为8,线程高拉维斯出圈

    哪个线程正在运行?约翰 计数为6

    哪个线程正在运行?约翰 计数为7

    哪个线程正在运行?约翰 计数为8

    计数为8,线程Johnis退出循环

    我已经回答过了- "implements Runnable" vs. "extends Thread" ,其中一条注释是 然而,实现Runnable和扩展Thread之间的一个显著区别是 通过扩展Thread,每个线程都有一个与其关联的唯一对象,而 实现Runnable时,许多线程可以共享同一个对象实例。

    因此,如果线程可以共享同一个对象,那么像count这样的实例值应该由两者共享。为什么我的输出是这样的。

    2 回复  |  直到 8 年前
        1
  •  1
  •   jjlema    10 年前

    为了实现这一点,您可以创建两个线程,并让一个线程等待另一个线程,您可以在这里阅读关于连接线程的内容:

    http://docs.oracle.com/javase/tutorial/essential/concurrency/join.html

    我在想:

    public class Counter extends Thread {
        private final int countFrom;
        private final int countTo;
        private final Counter counterToWaitFor;
    
        public Counter(final int countFrom, final int countTo, final Counter counterToWaitFor) {
            super();
            this.countFrom = countFrom;
            this.countTo = countTo;
            this.counterToWaitFor = counterToWaitFor;
        }
    
        @Override
        public void run() {
            if (this.counterToWaitFor != null) {
                try {
                    this.counterToWaitFor.join();
                } catch (final InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (int i = this.countFrom; i <= this.countTo; i++) {
                System.out.println("i= " + i);
            }
        }
    }
    

    主要是:

    public static void main(final String[] args) throws IOException, InterruptedException {
        final Counter t1 = new Counter(1, 5, null);
        final Counter t2 = new Counter(6, 8, t1);
        t1.start();
        t2.start();
    }
    
        2
  •  1
  •   Peter Lawrey    10 年前

    一个简单的解决方案是使用Java 8 Streams API

    IntStream.rangeClosed(1, 8).parallel()
             .forEach(System.out::println);
    

    这可以用更少的代码使用机器中的所有CPU。

    通过扩展Thread,每个线程都有一个与其关联的唯一对象,而实现Runnable,许多线程可以共享同一个对象实例。

    事实上,这在这方面没有什么区别,你可以在这两种情况下都这样做。

    避免对线程进行子类化的原因是避免在调用重写方法时发生混淆。

    为什么我的输出是这样的。

    您正在共享一个没有线程安全的对象。