Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
多线程java程序交替打印偶数和奇数_Java_Multithreading_Synchronization - Fatal编程技术网

多线程java程序交替打印偶数和奇数

多线程java程序交替打印偶数和奇数,java,multithreading,synchronization,Java,Multithreading,Synchronization,在一次采访中,我被要求编写一个双线程Java程序。在这个程序中,一个线程应该打印偶数,另一个线程应该交替打印奇数 样本输出: 线程1:1 线程2:2 线程1:3 线程2:4 ... 等等 我写了下面的程序。一个类任务,它包含两种分别打印偶数和奇数的方法。在main方法中,我创建了两个线程来调用这两个方法。面试官要求我进一步改进,但我想不出有什么改进。有没有更好的方法来编写相同的程序 class Task { boolean flag; public Task(boolean f

在一次采访中,我被要求编写一个双线程Java程序。在这个程序中,一个线程应该打印偶数,另一个线程应该交替打印奇数

样本输出:

线程1:1

线程2:2

线程1:3

线程2:4 ... 等等

我写了下面的程序。一个类
任务
,它包含两种分别打印偶数和奇数的方法。在main方法中,我创建了两个线程来调用这两个方法。面试官要求我进一步改进,但我想不出有什么改进。有没有更好的方法来编写相同的程序

class Task
{
    boolean flag;

    public Task(boolean flag)
    {
        this.flag = flag;
    }
    public void printEven()
    {
        for( int i = 2; i <= 10; i+=2 )
        {
            synchronized (this)
            {
                try
                {
                    while( !flag )
                        wait();
                    System.out.println(i);
                    flag = false;
                    notify();
                }
                catch (InterruptedException ex)
                {
                    ex.printStackTrace();
                }
            }
        }
    }
    public void printOdd()
    {
        for( int i = 1; i < 10; i+=2 )
        {
            synchronized (this)
            {
                try
                {
                    while(flag )
                        wait();
                    System.out.println(i);
                    flag = true;
                    notify();
                }
                catch(InterruptedException ex)
                {
                    ex.printStackTrace();
                }
            }
        }
    }
}

public class App {
    public static void main(String [] args)
    {
        Task t = new Task(false);
        Thread t1 = new Thread( new Runnable() {
           public void run()
           {
               t.printOdd();
           }
        });
        Thread t2 = new Thread( new Runnable() {
            public void run()
            {
                t.printEven();
            }
        });
        t1.start();
        t2.start();
    }
}
类任务
{
布尔标志;
公共任务(布尔标志)
{
this.flag=flag;
}
公共无效打印偶()
{

对于(int i=2;i嗯,有很多选择。我可能会使用
SynchronousQueue
来代替(我不喜欢低级
wait
/
notify
并尝试使用高级并发原语)。此外,
printOdd
printEven
可以合并到单个方法中,不需要附加标志:

public class App {
    static class OddEven implements Runnable {
        private final SynchronousQueue<Integer> queue = new SynchronousQueue<>();

        public void start() throws InterruptedException {
            Thread oddThread = new Thread(this);
            Thread evenThread = new Thread(this);
            oddThread.start();
            queue.put(1);
            evenThread.start();
        }

        @Override
        public void run() {
            try {
                while (true) {
                    int i = queue.take();
                    System.out.println(i + " (" + Thread.currentThread() + ")");
                    if (i == 10)
                        break;
                    queue.put(++i);
                    if (i == 10)
                        break;
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new OddEven().start();
    }
}
公共类应用程序{
静态类Odd偶数实现可运行{
private final SynchronousQueue=new SynchronousQueue();
public void start()引发InterruptedException{
螺纹oddThread=新螺纹(此);
线程evenThread=新线程(此线程);
oddThread.start();
队列。put(1);
evenThread.start();
}
@凌驾
公开募捐{
试一试{
while(true){
int i=queue.take();
System.out.println(i+“(“+Thread.currentThread()+”);
如果(i==10)
打破
queue.put(++i);
如果(i==10)
打破
}捕捉(中断异常e){
抛出新的运行时异常(e);
}
}
}
公共静态void main(字符串[]args)引发InterruptedException{
新的奇偶();
}
}

像这样的短版本怎么样:

public class OddEven implements Runnable {
    private static volatile int n = 1;

    public static void main(String [] args) {
        new Thread(new OddEven()).start();
        new Thread(new OddEven()).start();
    }

    @Override
    public void run() {
        synchronized (this.getClass()) {
            try {
                while (n < 10) {
                    this.getClass().notify();
                    this.getClass().wait();
                    System.out.println(Thread.currentThread().getName() + ": " + (n++));
                    this.getClass().notify();
                }
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }   
}
public类Odd偶数实现可运行{
私有静态易失性int n=1;
公共静态void main(字符串[]args){
新线程(新的奇偶数()).start();
新线程(新的奇偶数()).start();
}
@凌驾
公开募捐{
已同步(this.getClass()){
试一试{
而(n<10){
this.getClass().notify();
this.getClass().wait();
System.out.println(Thread.currentThread().getName()+“:”+(n++);
this.getClass().notify();
}
}捕获(中断异常例外){
例如printStackTrace();
}
}
}   
}

正确启动线程有一点技巧-因此需要额外的
notify()
来启动整个过程(而不是让两个进程都等待,或者要求主线程调用notify)另外,为了处理线程启动的可能性,在第二个线程启动之前,它是否工作并调用notify:)

我的初始答案不起作用。编辑:

package test;

public final class App {

    private static volatile int counter = 1;
    private static final Object lock = new Object();

    public static void main(String... args) {
        for (int t = 0; t < 2; ++t) {
            final int oddOrEven = t;
            new Thread(new Runnable() {
                @Override public void run() {
                    while (counter < 100) {
                        synchronized (lock) {
                            if (counter % 2 == oddOrEven) {
                                System.out.println(counter++);
                            }
                        }
                    }
                }
            }).start();
        }
    }
}
封装测试;
公共期末课程应用程序{
专用静态易失性int计数器=1;
私有静态最终对象锁=新对象();
公共静态void main(字符串…参数){
对于(int t=0;t<2;++t){
最终int oddOrEven=t;
新线程(newrunnable()){
@重写公共无效运行(){
同时(计数器<100){
已同步(锁定){
if(计数器%2==oddOrEven){
System.out.println(计数器++);
}
}
}
}
}).start();
}
}
}
有没有更好的方法来编写相同的程序

class Task
{
    boolean flag;

    public Task(boolean flag)
    {
        this.flag = flag;
    }
    public void printEven()
    {
        for( int i = 2; i <= 10; i+=2 )
        {
            synchronized (this)
            {
                try
                {
                    while( !flag )
                        wait();
                    System.out.println(i);
                    flag = false;
                    notify();
                }
                catch (InterruptedException ex)
                {
                    ex.printStackTrace();
                }
            }
        }
    }
    public void printOdd()
    {
        for( int i = 1; i < 10; i+=2 )
        {
            synchronized (this)
            {
                try
                {
                    while(flag )
                        wait();
                    System.out.println(i);
                    flag = true;
                    notify();
                }
                catch(InterruptedException ex)
                {
                    ex.printStackTrace();
                }
            }
        }
    }
}

public class App {
    public static void main(String [] args)
    {
        Task t = new Task(false);
        Thread t1 = new Thread( new Runnable() {
           public void run()
           {
               t.printOdd();
           }
        });
        Thread t2 = new Thread( new Runnable() {
            public void run()
            {
                t.printEven();
            }
        });
        t1.start();
        t2.start();
    }
}
好的,问题是,编写程序的唯一好方法是使用一个线程。如果你想让一个程序按这个顺序执行X,Y,Z,那么就编写一个执行X,Y,Z的过程。没有比这更好的方法了

以下是我在与面试官讨论了这些主题的恰当性之后所写的内容

import java.util.concurrent.SynchronousQueue;
import java.util.function.Consumer;

public class EvenOdd {
    public static void main(String[] args) {
        SynchronousQueue<Object> q1 = new SynchronousQueue<>();
        SynchronousQueue<Object> q2 = new SynchronousQueue<>();
        Consumer<Integer> consumer = (Integer count) -> System.out.println(count);
        new Thread(new Counter(q1, q2, 2, 1, consumer)).start();
        new Thread(new Counter(q2, q1, 2, 2, consumer)).start();
        try {
            q1.put(new Object());
        } catch (InterruptedException ex) {
            throw new RuntimeException(ex);
        }
    }

    private static class Counter implements Runnable {
        final SynchronousQueue<Object> qin;
        final SynchronousQueue<Object> qout;
        final int increment;
        final Consumer<Integer> consumer;
        int count;

        Counter(SynchronousQueue<Object> qin, SynchronousQueue<Object> qout,
                int increment, int initial_count,
                Consumer<Integer> consumer) {
            this.qin = qin;
            this.qout = qout;
            this.increment = increment;
            this.count = initial_count;
            this.consumer = consumer;
        }

        public void run() {
            try {
                while (true) {
                    Object token = qin.take();
                    consumer.accept(count);
                    qout.put(token);
                    count += increment;
                }
            } catch (InterruptedException ex) {
                throw new RuntimeException(ex);
            }
        }
    }
}
import java.util.concurrent.SynchronousQueue;
导入java.util.function.Consumer;
公共课偶数{
公共静态void main(字符串[]args){
SynchronousQueue q1=新的SynchronousQueue();
SynchronousQueue q2=新的SynchronousQueue();
消费者消费者=(整数计数)->System.out.println(计数);
新线程(新计数器(q1、q2、2、1、使用者)).start();
新线程(新计数器(q2、q1、2、2、使用者)).start();
试一试{
q1.放置(新对象());
}捕获(中断异常例外){
抛出新的运行时异常(ex);
}
}
私有静态类计数器实现可运行{
最终同步队列;
最终同步队列qout;
最终整数增量;
最终消费者;
整数计数;
计数器(SynchronousQueue qin、SynchronousQueue qout、,
整数增量,整数初始计数,
(消费者){
this.qin=qin;
this.qout=qout;
这个增量=增量;
this.count=初始计数;
这个。消费者=消费者;
}
公开募捐{
试一试{
while(true){
对象标记=qin.take();
消费者。接受(计数);
qout.put(令牌);
计数+=增量;
}
}抓住(我)