Java线程:如何一次使用两个线程打印字母和数字

时间:2017-08-17 11:20:59

标签: java multithreading thread-synchronization

我正在尝试使用java中的线程。虽然我知道线程输出是不可预测的,但是想知道是否有办法做到这一点。

我必须实现两个线程,一个打印字母(a,b,c...z)和其他打印数字(1,2,3....26)。必须以输出应为a,1,b,2,c,3,d,4......z,26的方式实现它。下面是我的代码,但它没有给出所需的输出。

public class ThreadsExample {

  public static void main(String[] args) {
    Runnable r = new Runnable1();
    Thread t = new Thread(r);
    Runnable r2 = new Runnable2();
    Thread t2 = new Thread(r2);
    t.start();
    t2.start();
  }
}

class Runnable2 implements Runnable{
  public void run(){
    for(char i='a';i<='z';i++) {
        System.out.print(i+",");
    }
  }
}

 class Runnable1 implements Runnable{
  public void run(){
    for(int i=1;i<=26;i++) {
       System.out.print(i+",");
    }
 }
}

我应该在代码中进行哪些调整才能获得所需的输出? synchronization如何帮助?或者在使用Threads时真的可以吗?

PS:这不是作业或一些练习。它的自我学习。

5 个答案:

答案 0 :(得分:3)

线程的整个概念:它代表一个“活动流”,它独立于其他线程执行代码。

在你的情况下,你希望这两个线程进入“锁步”。线程A执行一步,然后是线程B,然后是A,然后是B。

为了实现这一目标,两个线程需要“同步” - 换句话说:A在完成其步骤时向B发送信号 - 并且B必须等待信号。然后B做了它的事情,向A发出信号......

对于初学者来说,一个简单的布尔值就可以了。一个线程将其设置为true,另一个线程将其设置为false(以指示何时执行其步骤)。然后线程等待布尔再次切换。

当你打算学习东西时,我会从那里开始尝试。如果您想走弯路,请查看hereThis也可能有所帮助。

答案 1 :(得分:3)

有可能。你需要很好地同步它。

逼近伪代码

查询某些(同步)状态 州将告知是否允许使用nums或chars

如果state允许char和调用者将chars,现在就执行并更改状态并唤醒等待线程

如果没有,请等待

如果state允许数字,并且调用者将输入数字,立即执行并更改状态并唤醒等待线程

如果没有,请等待

Java代码

public class ThreadsExample {
  public static ThreadsExample output = new ThreadsExample ();

  public static void main(String[] args) {
    Runnable r = new Runnable1();
    Thread t = new Thread(r);
    Runnable r2 = new Runnable2();
    Thread t2 = new Thread(r2);
    t.start();
    t2.start();
  }

  private Object syncher = new Object ();  // we use an explicit synch Object, you could use annotation on methods, too. like ABHISHEK did.
             // explicit allows to deal with more complex situations, especially you could have more the one locking Object
  private int state = 0; // 0 allows chars, 1 allows ints

  public void print (char pChar) {
    synchronized (syncher) {      // prevent the other print to access state
        while (true) {
            if (state == 0) {     // char are allowed
                System.out.print(pChar + ","); // print it
                state = 1;        // now allow ints
                syncher.notify(); // wake up all waiting threads
                return;
            } else {              // not allowed for now
                try {
                    syncher.wait();  // wait on wake up
                } catch (InterruptedException e) {
                }
            }
        }
    }
  }

  public void print (int pInt) {
    synchronized (syncher) {
        while (true) {
            if (state == 1) {
                System.out.print(pInt + ",");
                state = 0;
                syncher.notify();
                return;
            } else {
                try {
                    syncher.wait();
                } catch (InterruptedException e) {
                }
            }
        }
     }
  }
}

class Runnable2 implements Runnable{
  public void run(){
    for(char i='a';i<='z';i++) {
        ThreadsExample.output.print(i);
    }
  }
}

 class Runnable1 implements Runnable{
  public void run(){
    for(int i=1;i<=26;i++) {
        ThreadsExample.output.print(i);
    }
 }
}

输出

A,1,B,2,C,3,d,4,E,5,F,6,克,7,H,8,I,9,J,10,K,11,升,12 ,米,13 N,14 O,15 p,16,q,17,R 18,S,19吨,20,U,21 v,22,W,23,X,24,Y ,25,Z,26

答案 2 :(得分:2)

这是代码:: 您需要创建2个线程并正确实现等待和通知方法,您也可以参考&#34; Create two threads, one display odd & other even numbers&#34;为你的答案。

    public class ThreadClass {
    volatile int i = 1;
    volatile Character c = 'a';
    volatile boolean state = true;

    synchronized public void printAlphabet() {
        try {
            while (!state) {
                wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " " +c);
        state = false;
        c++;
        notifyAll();
    }
    synchronized public void printNumbers() {
        try {
            while (state) {
                wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " " + i);
        state = true;
        i++;
        notifyAll();
    }
    public static void main(String[] args) {
        ThreadClass threadClass = new ThreadClass();
        Thread t1 = new Thread() {
            int k = 0;
            @Override
            public void run() {
                while (k < 26) {
                    threadClass.printAlphabet();
                    k++;
                }
            }
        };
        t1.setName("Thread1");
        Thread t2 = new Thread() {
            int j = 0;

            @Override
            public void run() {
                while (j < 26) {
                    threadClass.printNumbers();
                    j++;
                }
            }
        };
        t2.setName("Thread2");

        t1.start();

        t2.start();
    }
}

答案 3 :(得分:0)

您的主题同时运行。但不是你想要它的方式,如上所述。您将看到来自线程1的数据块,然后是来自线程2的数据块;这是因为线程调度。线程1只是在线程2之前对其输出进行排队。

要测试这个理论,请将输出增加到1000条记录,例如字母和26个数字不是很大。

通过这样做,您将看到这些“数据块”。有一种方法可以做你提到的,但这是不可取的,因为这并不是说明线程实际上是如何工作的,而是你强迫它以这种方式工作。

答案 4 :(得分:0)

使用更少的代码:

class MyRunnable implements Runnable {
    private static int n = 1;
    private static char c = 'a';

    public void run() {
        for (int i = 1; i <= 26; i++) {
            synchronized (this) {
                try {
                    notifyAll();
                    if (Thread.currentThread().getName().equals("A")) {
                        System.out.print(c + ",");
                        c++;
                    } else {
                        System.out.print(n + ",");
                        n++;
                    }
                    if (i != 26) {
                        wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

public class PrintAlphabetNumberJob {

    public static void main(String[] args) throws InterruptedException {
        MyRunnable r = new MyRunnable();
        Thread tAlphabet = new Thread(r, "A");
        Thread tNumber = new Thread(r, "N");
        tAlphabet.start();
        Thread.sleep(100);
        tNumber.start();
    }

}