簡體   English   中英

編寫具有 2 個線程的程序,交替打印

[英]Writing a program with 2 threads which prints alternatively

我最近在一次采訪中被問到這個問題。

編寫一個具有兩個線程(A 和 B)的程序,其中 A 打印 1 , B 打印 2 ,依此類推,直到達到 50。

我們該怎么做呢?

賦值的本質是演示一個線程如何向另一個線程發出信號。 最常見的方式是使用阻塞隊列,但是這里一個信號不攜帶任何信息,所以一個信號量就足夠了。

創建使用 2 個信號量參數化的線程類:輸入和輸出:

class ThreadPrinter implements Runnable {
    int counter;
    Semaphore ins, outs;

    ThreadPrinter(int counter, Semaphore ins, Semaphore outs) {
        this.counter = counter;
        this.ins = ins;
        this.outs = outs;
    }

    @Override
    public void run() {
        for (int i = 0; i < 25; i++) {
            ins.aquire(); // wait for permission to run
            System.out.println("" + counter);
            outs.release();  // allow another thread to run
            counter += 2;
        }
    }

創建 2 個Semaphore並將它們傳遞給 2 個線程:

Semaphore a = new Semaphore(1);  // first thread is allowed to run immediately
Semaphore b = new Semaphore(0); // second thread has to wait
ThreadPrinter tp1 = new ThreadPrinter(1, a, b);
ThreadPrinter tp2 = new ThreadPrinter(2, b, a); 

注意信號量ab以不同的順序傳遞。

public class Test {

private static int count = 0;

public static void main(String[] args) throws InterruptedException {

    Thread t1 = new Thread(new Runnable() {

        @Override
        public void run() {

            for (int i = 0; i < 25; i++) {
                synchronized (CommonUtil.mLock) {
                    incrementCount();
                    CommonUtil.mLock.notify();
                    try {
                        CommonUtil.mLock.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    });
    Thread t2 = new Thread(new Runnable() {

        @Override
        public void run() {

            for (int i = 0; i < 25; i++) {
                synchronized (CommonUtil.mLock) {
                    incrementCount();
                    CommonUtil.mLock.notify();
                    try {
                        CommonUtil.mLock.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    });
    t1.start();
    Thread.sleep(400);
    t2.start();
    t1.join();
    t2.join();
}

private static void incrementCount() {

    count++;
    System.out.println("Count: " + count + " icnremented by: " +        Thread.currentThread().getName());
}
}
  class CommonUtil {

 static final Object mLock = new Object();
   }

我遇到了同樣的問題,預計只使用基礎知識,所以我選擇在線程之間的共享對象上等待通知

public class Message implements Runnable {

    private static final int N = 10;
    private Thread thread;
    private static Object object = new Object();

    public Message(String name){
        thread = new Thread(this, name);
        thread.start();
    }

    public void run(){
        for(int i=0; i<N; i++){
            synchronized (object) {
                System.out.println(i + "--" + thread.getName());
                object.notify();
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }
}

在主要方法中:

Message message1 = new Message("Ping");
Message message2 = new Message("Pong");

嗨,請在這里找到答案...模式 ABABABAB

package com.abhi.ThreadPractice;

    public class Test {

        public static void main(String[] args) throws InterruptedException {

          final Object lock = new Object();
          Thread t1 = new Thread(new Runnable() {

            @Override
           public void run() {
            for (int i = 0; i < 10; i++) {

              synchronized (lock) {
             // count++;
              System.out.println("A");
              try {
               lock.wait();
               lock.notify();
              } catch (InterruptedException e) {
               e.printStackTrace();
              }
             }
            }
           }
          });             

           Thread t2 = new Thread(new Runnable() {

            @Override
           public void run() {
            for (int i = 0; i < 10; i++) {
             synchronized (lock) {
              lock.notify();
              //count++;
              System.out.println("B");
              try {
               lock.wait();
              } catch (InterruptedException e) {
               e.printStackTrace();
              }
             }
            }
           }
          });

           t1.start();
          t2.start();
          t1.join();
          t2.join();

          }

        }

可能這仍然是相關的:

public class MyRunnable implements Runnable {
    public static int counter = 0;
    public static int turn = 0;
    public static Object lock = new Object();

    @Override
    public void run() {
        while (counter < 50) {
            synchronized (lock) {
                if (turn == 0) {

                    System.out.println(counter + " from thread "
                            + Thread.currentThread().getName());
                    turn = 1;
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                } else {
                    turn = 0;
                    lock.notify();
                }

            }
        }
    }
}

然后是主函數

public static void main(String[] args) {
        Thread threadA = new Thread(new MyRunnable());
        Thread threadB = new Thread(new MyRunnable ());
        threadA.start();
        threadB.start();
}
public class PingPong extends Thread {
static StringBuilder object = new StringBuilder("");

public static void main(String[] args) throws InterruptedException {

    Thread t1 = new PingPong();
    Thread t2 = new PingPong();

    t1.setName("\nping");
    t2.setName(" pong");

    t1.start();
    t2.start();
}

@Override
public void run() {
    working();
}

void working() {
    while (true) {
        synchronized (object) {
            try {
                System.out.print(Thread.currentThread().getName());
                object.notify();
                object.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

}

public class ThreadCounter implements Runnable {
    private static int count = 0;

    private Thread t;

    public ThreadCounter(String tName){
        t= new Thread(this, tName);
        t.start();
    }

    @Override
    public void run() {
        for(int i=1; i<=5; i++){
            synchronized (CommonUtil.mLock) {
                incrementCount(t.getName());
                CommonUtil.mLock.notify();
                try {
                    CommonUtil.mLock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void incrementCount(String tName){
        System.out.println(tName+": "+(++ThreadCounter.count));
    }

    public static void main(String[] args) throws InterruptedException {
        new ThreadCounter("Thread1");
        Thread.sleep(500);
        new ThreadCounter("Thread2");
    }

}

class CommonUtil{
    public static Object mLock = new Object();
}

這是我能想到的最簡單的解決方案。 它使用同步方法並使用notify() 和wait() 交替打印數字。 希望能幫助到你。 :)

 public class program implements Runnable
    {
        static int count =1;
        private static final int MAX_COUNT = 50;
        public synchronized void print ()
        {
            System.out.println(Thread.currentThread().getName() + " is printing " + count);
            count++;
            notify();
            try{
                if(count>MAX_COUNT)
                    return;
                wait();
            }catch (InterruptedException e){ 
                e.printStackTrace();
            }
        }
        public void run()
        {
            for(int i=0;i<MAX_COUNT/2;i++)
            {
                print();

            }
        }

        public static void main(String[] args) {

            program x= new program();
            Thread t0= new Thread(x);
            Thread t1=  new Thread(x);
            t0.start();
            try
            {
                Thread.sleep(1);
            } catch (InterruptedException e){
                e.printStackTrace();
            }
            t1.start();     
        }


    }
//simply use wait and notify and and set a counter and it will do  

public class ThreadalternatePrint implements Runnable {
    static int counter =0; 
    @Override
    public synchronized void run() {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        while(counter<51)
        {   ++counter;
        notify();
        System.out.println(Thread.currentThread().getName());
            try {
                    wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
        }       
    }

    public static void main(String[] args) {
        ThreadalternatePrint obj1 = new ThreadalternatePrint();
        Thread Th1 = new Thread(obj1);
        Thread Th2 = new Thread(obj1);
        Th1.setName("Thread1");
        Th2.setName("Thread2");
        Th1.start();
        Th2.start();
    }


}
public class Testing implements Runnable {
private static int counter = 1;
private static final Object lock = new Object();

public static void main(String[] args)  {

    Thread t1 = new Thread(new Testing(), "1");
    t1.start();
    Thread t2 = new Thread(new Testing(), "2");
    t2.start();

}

@Override
public void run() {
    while (counter<=100) {
        synchronized (lock) {
            if (counter % 2 == 0) {
                System.out.println(counter +" Written By Thread-"+ Thread.currentThread().getName());
                counter++;
                try {
                    lock.notifyAll();
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            } else if (counter % 2 == 1) {
                System.out.println(counter +" Written By Thread-"+ Thread.currentThread().getName());
                counter++;

                try {
                    lock.notifyAll();
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }
  }
}

我使用可重入鎖為它創建了一個非常基本的解決方案。

package com.multithreding.trylock;

import java.util.concurrent.locks.ReentrantLock;

public class TryLock extends Thread {

    static int intitialCount = 50;          //Value till which you want to print
    int valueToSubtract = 0;                //Value by which difference you want to print the series like 1,2,3
    static ReentrantLock alternate = new ReentrantLock();

    public TryLock(String name) {
        this.setName(name);
    }

    public void run() {
        while (intitialCount > 1) {         

            if (valueToSubtract > 0) {
                alternate.lock();
                intitialCount = intitialCount - valueToSubtract;
                valueToSubtract = 0;
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("value Subtracted " + intitialCount + " by the Thread" + this.getName());
                alternate.unlock();
            } else {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                valueToSubtract++;
            }
        }

    }

}

package com.multithreding.trylock;

public class AlternatePrint {

    public static void main(String[] args) throws InterruptedException{
        //You  can add as many thread to print then in different number of series
        TryLock t1 = new TryLock("Odd One");
        TryLock t2 = new TryLock("Even Value");
        t1.start();
        t2.start();

    }

}

這個解決方案也是模塊化的,

  • 您可以添加“n”個線程來打印替代系列。 即一次使用 3 個線程

  • 您還可以打印多個差值大於 1 的系列。即 1,3,5 等

package thread;

public class Pingpong extends Thread {
    static StringBuilder object = new StringBuilder("");
    static int i=1;

    @Override
    public void run() {
        working();
    }
    void working() {
        while (i<=10) {
            synchronized (object) {
                try {
                    System.out.println(Thread.currentThread().getName() +"  "+ i);
                    i++;
                    object.notify();
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Pingpong();
        Thread t2 = new Pingpong();
        t1.setName("Thread1");
        t2.setName("Thread2");
        t1.start();
        t2.start();
    }
}

Thread1  1
Thread2  2
Thread1  3
Thread2  4
Thread1  5
Thread2  6
Thread1  7
Thread2  8
Thread1  9
Thread2  10

這個答案是通用的,即不僅從 2 個線程交替打印數字,而且交替執行 2 個線程。 上述方法值得稱道,但這種方法不需要任何鎖,而是使用 AtomicInteger 變量和 2 個 AtomicBooleans 來指示一個線程何時完成執行,以便另一個線程可以完成剩余執行的其余部分。

這將適用於所有 3 種情況:

  1. 當兩個線程的執行次數相同時。
  2. 當第一個線程在第二個線程之前完成並且第二個線程的執行次數比第一個線程多時。
  3. 當第二個線程在第一個線程之前完成並且第一個線程的執行次數比第二個線程多時。
public class TestAlternateExecutionOfTwoThreads
{
    private static final AtomicInteger count = new AtomicInteger(0);
    private static final AtomicBoolean firstIsDone = new AtomicBoolean(false);
    private static final AtomicBoolean secondIsDone = new AtomicBoolean(false);

    // change the below values to change the number of iterations each thread should 
    // run. In this example, the initial value are hard-coded but you can change 
    // them as well.
    private static final int finalOfFirstThread = 10;
    private static final int finalOfSecondThread = 109;

    public static void main(String[] args)
    {
        Runnable r1 = () -> {
            int i = 1;
            for(; i <= finalOfFirstThread; )
            {
                while(count.get() == 0)
                {
                    System.out.println(i);
                    count.incrementAndGet();
                    i++;
                }
                if(count.get() == 1 && secondIsDone.get() && i != (finalOfFirstThread + 1))
                {
                    System.out.println(i);
                    i++;
                }
            }
            firstIsDone.set(true);
        };

        Runnable r2 = () -> {
            int j = 100;
            for (; j <= finalOfSecondThread; )
            {
                while(count.get() == 1)
                {
                    System.out.println(j);
                    count.decrementAndGet();
                    j++;
                }
                if(count.get() == 0 && firstIsDone.get() && j != (finalOfSecondThread + 1))
                {
                    System.out.println(j);
                    j++;
                }
            }
            secondIsDone.set(true);
        };

        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r2);

        t1.start();
        t2.start();

    }
}

這是另一種解決方案:

     Thread t1 = new Thread(new Runnable() {

        @Override
        public void run() {
            synchronized (lock) {
                for (int i = 1; i <= 50; i += 2) {
                    System.out.println("T1=" + i);

                    t1turn = false;
                        try {
                            lock.notifyAll();
                            lock.wait();
                        } catch (InterruptedException e) {
                        }
                }
            }

        }
    });
    Thread t2 = new Thread(new Runnable() {

        @Override
        public void run() {
            synchronized (lock) {
                for (int i = 2; i <= 50; i += 2) {
                    if (t1turn)
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                        }
                    System.out.println("T2=" + i);
                    t1turn = true;
                    lock.notify();
                }
            }
        }
    });
    t1.start();
    t2.start();

我想這可能會有所幫助。 雖然它不是標准的,但我希望它提供一種更簡單的方法。

public class ThreadDemo
{
    public static void main (String [] args)
    {
        PrintDemo pd=new PrintDemo();     
        MyThread1 mt1 = new MyThread1 ("T1",pd);
        MyThread2 mt2 = new MyThread2 ("T2",pd);     
        mt1.start ();
        mt2.start();
    }
}
class PrintDemo {
    private boolean oddFlag=true;
    public synchronized void printOdd(int i,String tName){
        if(oddFlag==false){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }   
        }else{
            System.out.println("\nThread "+tName+" count:"+i);
            oddFlag=false;
            notify();
        }
    }
    public synchronized void printEven(int i,String tName){
        if(oddFlag==true){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }   
        }else{
            System.out.println("\nThread "+tName+" count:"+i);
            oddFlag=true;
            notify();
        }
    }   
}
class MyThread1 extends Thread
{
    private PrintDemo pd;
    private String name;

    MyThread1(String threadName,PrintDemo pd){
        this.name=threadName;
        this.pd=pd;
    }  
    public void run ()  
    {
       for(int i=1;i<=50;i+=2){
            pd.printOdd(i,name);
       }
    }
}
class MyThread2 extends Thread
{
    private PrintDemo pd;
    private String name;    
    MyThread2(String threadName,PrintDemo pd){
        this.name=threadName;
        this.pd=pd;
    }   
    public void run ()
    {
        for(int i=2;i<=50;i+=2){
            pd.printEven(i,name);                   
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM