1

複数のスレッドがシーケンスの代替値を出力する実装を作成しようとしています。したがって、ここでは、thread1は1,4,7を印刷し、thread2は2,5,8を印刷し、thread3は3,6,9を印刷します。アトミック整数とモジュロ関数を使用しています。

以下の実装は、最初のスレッドが1,4,7を出力し、2番目のスレッドが2,5,8を出力し、3番目のスレッドが3,6,9を出力するという意味で正常に機能しますが、問題はシーケンスが維持されないことです。つまり、出力は1,3,2のようになります。 、4,5,7,8,6,9ですが、適切なスレッドがそれらの値を出力するときにシーケンスを維持したいのです。1つの条件は、同期を使用したくないということです。[学習目的のためだけに]

import java.util.concurrent.atomic.AtomicInteger;

public class ThreeThreadsOrderedLockLess {

    AtomicInteger sharedOutput = new AtomicInteger(0);

    public static void main(String args[]) {



        ThreeThreadsOrderedLockLess t = new ThreeThreadsOrderedLockLess();



        ThreadTasks t1 = t.new ThreadTasks(0);
        ThreadTasks t2 = t.new ThreadTasks(1);
        ThreadTasks t3 = t.new ThreadTasks(2);

        Thread ts1 = new Thread(t1);
        Thread ts2 = new Thread(t2);
        Thread ts3 = new Thread(t3);
        ts1.start();
        ts2.start();
        ts3.start();

    }

    private class ThreadTasks implements Runnable {

        private final int threadPosition;


        public ThreadTasks(int threadPosition) {
            super();

            this.threadPosition = threadPosition;
        }

        @Override
        public void run() {

            while (sharedOutput.get() < 9) {

                if (sharedOutput.get() % 3 == this.threadPosition) {

                    System.out.println("Printing output for Thread: "
                            + this.threadPosition + "  "
                            + sharedOutput.incrementAndGet());
                }
            }

        }
    }

}
4

15 に答える 15

3

最初に印刷し、その後にインクリメントする必要があります。

int value = sharedOutput.get() + 1;
System.out.println("Printing output for Thread: "
                        + this.threadPosition + "  "
                        + value);
sharedOutput.incrementAndGet();

とはいえ、すべてのスレッドがループでビジー状態になっているため、CPU使用率が100%になります。代わりにスレッドを同期する必要があります。

于 2013-03-10T13:43:31.070 に答える
2

以下のコードスニペットは番号を順番に出力し、すべてのスレッドはタスクの後に正常に終了します。数値を印刷するためにスレッドセーフであるAtomicIntegerを使用し、同じロジックを適用して、任意の数のスレッドで任意の数値まで印刷することができます。

 
    import java.util.concurrent.atomic.AtomicInteger;

    パブリッククラスPrintNumSequence
    {{
        public static void main(String [] args)
        {{
          AtomicInteger atomicInteger = new AtomicInteger(0);
          new NumPrinter(atomicInteger、0).start(); // thread0
          new NumPrinter(atomicInteger、1).start(); // thread1
          new NumPrinter(atomicInteger、2).start(); // thread2

        }
    }

    クラスNumPrinterはスレッドを拡張します
    {{

        プライベートAtomicIntegeratomicInteger;
        private int threadNum;

       public NumPrinter(AtomicInteger atomicInteger、int threadNum)
       {{
        this.atomicInteger = atomInteger;
        this.threadNum = threadNum;
       }

       @オーバーライド
       public void run()
       {{
        int num = atomInteger.intValue();
        行う
        {{
            同期(atomicInteger)
            {{
                num = atomInteger.intValue();
                //番号が9の場合、停止します。
                if(num> 9)
                {{
                    atomicInteger.notifyAll();
                    壊す;
                }
                //3はスレッド数です
                if((num%3)== threadNum)
                {{
                    System.out.println( "Thread-" + threadNum + "->" + num);
                    num = atomInteger.incrementAndGet();

                }
                atomicInteger.notifyAll();
                試す
                {{
                    atomicInteger.wait();
                }
                catch(InterruptedException e)
                {{
                    e.printStackTrace();
                }
            }
         } while(true);
       }
     }
于 2016-07-22T19:38:10.160 に答える
0

これは、各スレッドのタイムスライスがOSによって決定されるためです。したがって、スレッドxが共有番号をインクリメントする可能性がありますが、タイムスライスは、印刷する前に次のスレッドyに渡されます。次のスレッドyは、共有番号を読み取り、インクリメント後に印刷します(スレッドyがスレッドxよりも多くの時間を費やして、インクリームと印刷を行ったと仮定します)共有番号)。

于 2013-03-10T13:42:37.810 に答える
0

Javaのwait()、notify()、notifyall()メソッドを使用します。これらのメソッドの
このチュートリアルもご覧ください。

これがあなたの問題を解決するのに役立つことを願っています。。。

この例の出力は次のとおりです。

プット:1
得た:1
プット:2
得た:2
プット:3
得た:3
プット:4
得た:4
プット:5
得た:5

于 2013-03-10T13:51:17.177 に答える
0

これは機能するはずです:

package com.sid;

import java.util.concurrent.atomic.AtomicInteger;

public class NumberSequence {

    private AtomicInteger sharedOutput = new AtomicInteger(0);
    private Object object = new Object();

    public static void main(String args[]) {

        NumberSequence t = new NumberSequence();

        ThreadTasks t1 = t.new ThreadTasks(0);
        ThreadTasks t2 = t.new ThreadTasks(1);
        ThreadTasks t3 = t.new ThreadTasks(2);

        Thread ts1 = new Thread(t1);
        Thread ts2 = new Thread(t2);
        Thread ts3 = new Thread(t3);

        ts1.start();
        ts2.start();
        ts3.start();

    }

    private class ThreadTasks implements Runnable {

        private final int threadPosition;

        public ThreadTasks(int threadPosition) {
            super();

            this.threadPosition = threadPosition;
        }

        @Override
        public void run() {

            while (sharedOutput.get() < 10) {

                synchronized (object) {

                    if (sharedOutput.get() % 3 == this.threadPosition) {

                        if(sharedOutput.get() < 10)
                        System.out.println("Printing output for Thread: "
                                + this.threadPosition + "  "
                                + sharedOutput.incrementAndGet());
                    }
                }
            }

        }
    }

}
于 2015-06-11T08:45:29.817 に答える
0

適切な同期は、明確な答えを得るのに役立ちます。実装を改善しました。質問を解決する必要があります。

    int threadId;
    int moduluos;
    int numOfThreads;

    public ThreadTasks(int id, int nubOfThreads) {
        threadId = id;
        this.numOfThreads = nubOfThreads;
        moduluos = threadId%numOfThreads;
    }

    public void run() {
        print();
    }

    private void print() {
        try {
            while (true) {
                synchronized (monitor) {
                    if (number.get() % numOfThreads != moduluos) {
                        monitor.wait();
                    } else {
                        System.out.println("ThreadId [" + threadId
                                + "] printing -->"
                                + number.getAndIncrement());
                        monitor.notifyAll();
                    }
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
于 2015-06-21T12:37:10.767 に答える
0
    package test.mk.thread;
import java.util.concurrent.atomic.AtomicInteger;

public class MkThread2 {
    int nextThreadToRun = 1;
    int[] arr = {1,2,3,4,5,6,7,8,9,10,11};
    AtomicInteger nextArrayIndex = new AtomicInteger(0);
    boolean token = true;

    public static void main(String[] args) {
        MkThread2 mkThread = new MkThread2();
        Thread t1 = new Thread(new Worker2(1, mkThread));
        Thread t2 =  new Thread(new Worker2(2, mkThread));
        Thread t3 =  new Thread(new Worker2(3, mkThread));
        t1.start();
        t2.start();
        t3.start();
    }
}


class Worker2 implements Runnable{
    volatile int threadNo;
    private MkThread2 mkThread;
    private String threadName;

    Worker2(int threadNo, MkThread2 mkThread){
        this.threadNo = threadNo;
        this.mkThread = mkThread;
        this.threadName = "Thread:"+threadNo ;
    }

    public void run(){
        try{
            synchronized (mkThread) {
                while(mkThread.token){
                    while(threadNo != mkThread.nextThreadToRun){
                        mkThread.wait();
                    }
                    if(mkThread.token){//double checking
                        System.out.print(threadName+ "->" + mkThread.arr[mkThread.nextArrayIndex.get()]);
                        if(threadNo == 3) System.out.println();
                        mkThread.nextThreadToRun = getNextThread(threadNo);
                        if(mkThread.nextArrayIndex.get() == mkThread.arr.length-1){
                            mkThread.token = false;
                        }
                        mkThread.nextArrayIndex.incrementAndGet();
                    }
                    mkThread.notifyAll();

                }
            }
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }

    private int getNextThread(int threadNo){
        int result = -1;
        switch (threadNo) {
        case (1):
            result = 2;
            break;
        case (2):
            result = 3;
            break;
        case (3):
            result = 1;
            break;
        }
        return result;
    }
}
于 2015-06-24T09:18:58.970 に答える
0
import java.util.concurrent.atomic.AtomicInteger; 
 public class Print123456789 {

public static void main(String[] args) {
    print p1 = new print(0);
    print p2 = new print(1);
    print p3 = new print(2);

    Thread t1 = new Thread(p1);
    Thread t2 = new Thread(p2);
    Thread t3 = new Thread(p3);

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


}

}



class print implements Runnable {
private int threadNumber;
private static AtomicInteger atomicInteger = new AtomicInteger(0);
public print(int threadNumber) {
    super();
    this.threadNumber = threadNumber;
}

public void run(){
    try{
    while(atomicInteger.get() < 10){
        synchronized (atomicInteger) {

            if((atomicInteger.get()%3) == this.threadNumber){
                System.out.println(atomicInteger.getAndIncrement() + " Thread :" + this.threadNumber );
                atomicInteger.notifyAll();
                }
            else
                atomicInteger.wait();
        }
    }
    }catch(InterruptedException e)
    {
        e.printStackTrace();
    }
}


}
于 2015-09-21T08:29:09.670 に答える
0

これは、ブロッキングキューを使用してより適切に実装できます。ブロッキングキューを保持しているワーカーを定義します。ワーカーは、キュー内の番号を受け取るまでキューで待機します。受け取った番号を出力し、インクリメントして、チェーン内の次のワーカーに渡します。完全な解決策については、こちらを参照してください。

于 2015-10-06T06:46:07.293 に答える
0
package threeThread;

class Task implements Runnable {

  String message;
  ThreeThread lock;
  int i = 0;
  int p;

  public Task(String text, ThreeThread obj, int p) {
    message = text;
    this.lock = obj;
    this.p = p;
  }

  @Override
  public void run() {

    while(true) {
        synchronized (lock) {

            while(!((lock.status % 3) == 0) && p == 1){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            while(!((lock.status % 3) == 1) && p == 2){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            while(!((lock.status % 3) == 2) && p == 3){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("thread: " + p + " : " + message);
            lock.status++;
            lock.notifyAll();
        }
    }
  }
}

public class ThreeThread {

  volatile int status = 0;
  public static void main(String[] args) {

    ThreeThread lock = new ThreeThread();
    Thread t1 = new Thread(new Task("Hello", lock,1));
    Thread t2 = new Thread(new Task("Good", lock,2));
    Thread t3 = new Thread(new Task("Morning", lock,3));
    t1.start();
    t2.start();
    t3.start();
  }

}
于 2016-09-08T15:21:05.003 に答える
0

私は5つのスレッドを使用して1-100を印刷するコードを入れています。任意の数のスレッドを使用して、ラウンドロビン方式で出力を印刷できます。

基本的な概念は、1つのオブジェクトをロックし、値の印刷を実行するように他のオブジェクトに通知することです。

public class PrintOneToHundredUsing5Threads {

    public static void main(String[] args) {
        List<Object> objList = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            objList.add(new Object());
        }
        for (int i = 0; i < 5; i++) {
            Thread t = new Thread(new PrintThread(objList.get(i), objList.get((i + 1) % 5)));
            t.setName("Thread" + i);
            t.start();
        }
    }

}

class PrintThread implements Runnable {
    Object current;
    Object next;
    volatile static int i = 1;

    PrintThread(Object cur, Object next) {
        this.current = cur;
        this.next = next;
    }

    @Override
    public void run() {
        for (; i <= 100;) {
            synchronized (current) {
                synchronized (next) {
                    next.notify();
                    System.out.println(Thread.currentThread().getName() + " Value : " + i++);
                }
                try {
                    current.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }

}
于 2016-10-08T19:15:41.657 に答える
0

以下のコードを使用して、複数のスレッドを使用して連番を印刷できます-

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class ThreadCall extends Thread {

    private BlockingQueue<Integer> bq = new ArrayBlockingQueue<Integer>(10);
    private ThreadCall next;

    public void setNext(ThreadCall t) {
        this.next = t;
    }

    public void addElBQ(int a) {
        this.bq.add(a);
    }

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

    @Override
    public void run() {
        int x = 0;
        while(true) {
            try {
                x = 0;
                x = bq.take();
                if (x!=0) {
                    System.out.println(Thread.currentThread().getName() + " =>" + x);
                    if (x >= 100) System.exit(0); // Need to stop all running threads
                    next.addElBQ(x+1);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        int THREAD_COUNT = 10;
        List<ThreadCall> listThread = new ArrayList<>();

        for (int i=1; i<=THREAD_COUNT; i++) {
            listThread.add(new ThreadCall("Thread " + i));
        }

        for (int i = 0; i < listThread.size(); i++) {
            if (i == listThread.size()-1) {
                listThread.get(i).setNext(listThread.get(0));
            }
            else listThread.get(i).setNext(listThread.get(i+1));
        }

        listThread.get(0).addElBQ(1);

        for (int i = 0; i < listThread.size(); i++) {
            listThread.get(i).start();
        }
    }
}

これで問題が解決することを願っています。

于 2017-04-03T11:09:09.867 に答える
0

ThreadSynchronizationクラスを使用して、「n」から「n」までの数値を出力できます。順番にスレッドの。ロジックは、連続する各スレッド間に共通のオブジェクトを作成し、「wait」、「notify」を使用して番号を順番に出力することです。注:最後のスレッドは、最初のスレッドとオブジェクトを共有します。

'maxThreads'値を変更して、プログラムを実行する前にプログラム内のスレッド数を増減できます。

import java.util.ArrayList;
import java.util.List;

public class ThreadSynchronization {

    public static int i = 1;
    public static final int maxThreads = 10;

    public static void main(String[] args) {
        List<Object> list = new ArrayList<>();
        for (int i = 0; i < maxThreads; i++) {
            list.add(new Object());
        }
        Object currObject = list.get(maxThreads - 1);
        for (int i = 0; i < maxThreads; i++) {
            Object nextObject = list.get(i);
            RunnableClass1 a = new RunnableClass1(currObject, nextObject, i == 0 ? true : false);
            Thread th = new Thread(a);
            th.setName("Thread - " + (i + 1));
            th.start();
            currObject = list.get(i);
        }
    }

}

class RunnableClass implements Runnable {

    private Object currObject;
    private Object nextObject;
    private boolean firstThread;

    public RunnableClass(Object currObject, Object nextObject, boolean first) {
        this.currObject = currObject;
        this.nextObject = nextObject;
        this.firstThread = first;
    }

    @Override
    public void run() {
        int i = 0;
        try {
            if (firstThread) {
                Thread.sleep(5000);
                firstThread = false;
                System.out.println(Thread.currentThread().getName() + " - " + ThreadSynchronization.i++);
                synchronized (nextObject) {
                    nextObject.notify();
                }
            }
            while (i++ < Integer.MAX_VALUE) {
                synchronized (currObject) {
                    currObject.wait();
                }
                System.out.println(Thread.currentThread().getName() + " - " + ThreadSynchronization.i++);
                Thread.sleep(1000);
                synchronized (nextObject) {
                    nextObject.notify();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
于 2017-06-18T08:31:27.333 に答える
0
public class PrintThreadsInSerial {
    public static void main(String[] args) {
    Thread t = new Thread(new Job());
    t.start();
    }
}

class Job implements Runnable {
    @Override
    public void run() {
     while (true) {
        for (int i = 1; i <= 3; i++) {
         System.out.println(i);
        }
     }
    }
}
于 2017-12-06T07:05:29.253 に答える
0
public class PrintSeqNumUsingAltThreads {

    public static void main(String[] args) {
        AtomicInteger counter = new AtomicInteger(0);
        int numThreads = 3;

        Thread t1 = new Thread(new SeqNumPrinter(counter, 0, numThreads));
        Thread t2 = new Thread(new SeqNumPrinter(counter, 1, numThreads));
        Thread t3 = new Thread(new SeqNumPrinter(counter, 2, numThreads));

        t1.currentThread().setName("T1");
        t2.currentThread().setName("T2");
        t3.currentThread().setName("T3");

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


public class SeqNumPrinter implements Runnable {

    AtomicInteger atmCounter;
    Integer threadPosition;
    Integer numThreads;

    public SeqNumPrinter(AtomicInteger counter, int position, int numThreads) {
        this.atmCounter = counter;
        this.threadPosition = position;
        this.numThreads = numThreads;
    }

    @Override
    public void run() {
        while (atmCounter.get() < 10) {
            if (atmCounter.get() % numThreads == threadPosition) {
                System.out.println("Printing value : " + atmCounter.getAndIncrement() + ", by thread : " + 
                        Thread.currentThread().getName());
            }
        }
    }
}

出力:

印刷値:0、スレッド別:スレッド0
印刷値:1、スレッド別:スレッド1
印刷値:3、スレッド別:スレッド0
印刷値:2、スレッド別:スレッド2
印刷値:4、スレッド:スレッド1
印刷値:6、スレッド別:スレッド0
印刷値:5、スレッド別:スレッド2
印刷値:7、スレッド別:スレッド1
印刷値:9、スレッド別:スレッド0
印刷値:8、スレッド別:スレッド-2

于 2018-10-27T06:47:13.780 に答える