1

我正在尝试创建一个实现,其中多个线程打印序列的替代值。所以这里 thread1 将打印 1,4,7 thread2 将打印 2,5,8 thread3 将打印 3,6,9。我正在使用原子整数和模函数。

下面的实现工作正常,第一个线程打印 1,4,7 而第二个线程打印 2,5,8 和第三个打印 3,6,9 但问题是没有保持序列,即输出可能像 1,3,2 ,4,5,7,8,6,9 而我希望将序列保持为适当的线程 shld 打印这些值。一个条件是我不想使用同步。[仅用于学习目的]

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();

也就是说,所有线程都忙于循环,这将导致 100% 的 CPU 使用率。您应该改为同步线程。

于 2013-03-10T13:43:31.070 回答
2

下面的代码片段将按顺序打印数字,所有线程将在任务完成后正常终止。使用 AtomicInteger,它对于打印数字是线程安全的,并且可以将相同的逻辑应用于打印,直到具有任意数量的线程的任意数字。

 
    导入 java.util.concurrent.atomic.AtomicInteger;

    公共类 PrintNumSequence
    {
        公共静态无效主要(字符串 [] 参数)
        {
          AtomicInteger atomicInteger = new AtomicInteger(0);
          new NumPrinter(atomicInteger, 0).start();// thread0
          new NumPrinter(atomicInteger, 1).start();// thread1
          new NumPrinter(atomicInteger, 2).start();// thread2

        }
    }

    类 NumPrinter 扩展线程
    {

        私有 AtomicInteger atomicInteger;
        私有 int 线程数;

       公共NumPrinter(AtomicInteger atomicInteger,int threadNum)
       {
        this.atomicInteger = atomicInteger;
        this.threadNum = 线程数;
       }

       @覆盖
       公共无效运行()
       {
        int num = atomicInteger.intValue();
        做
        {
            同步(atomicInteger)
            {
                数 = atomicInteger.intValue();
                // 如果数字是 9 则停止。
                如果(数字 > 9)
                {
                    atomicInteger.notifyAll();
                    休息;
                }
                // 3 是线程数
                if ((num % 3) == threadNum)
                {
                    System.out.println("线程-" + threadNum + " -->" + num);
                    num = atomicInteger.incrementAndGet();

                }
                atomicInteger.notifyAll();
                尝试
                {
                    atomicInteger.wait();
                }
                捕捉(InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
         } 而(真);
       }
     }
于 2016-07-22T19:38:10.160 回答
0

这是因为每个线程的时间片是由操作系统决定的。因此,线程 x 可能会增加共享编号,但在打印之前,时间片会传递给下一个线程 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
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

您可以使用以下代码使用多个线程打印序列号 -

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

我正在使用 5 个线程将代码打印 1-100。可以使用任意数量的线程以循环方式打印输出。

基本概念是锁定一个对象并通知另一个对象执行打印值。

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
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

ThreadSynchronization 类可用于打印“n”号之间的数字。线程的顺序。逻辑是在每个连续线程之间创建一个公共对象,并使用“等待”、“通知”来按顺序打印数字。注意:最后一个线程将与第一个线程共享一个对象。

您可以在运行程序之前更改“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

这可以使用阻塞队列更好地实现。定义一个持有阻塞队列的工作者。工作人员在队列中等待,直到它收到一个数字。它打印它收到的数字,增加它并将它传递给链中的下一个工人。请参阅此处以获取完整的解决方案。

于 2015-10-06T06:46:07.293 回答
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
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,按线程:Thread-0
打印值:1,按线程:Thread-1
打印值:3,按线程:Thread-0
打印值:2,按线程:Thread-2
打印值:4,按线程:Thread-1
打印值:6,按线程:Thread-0
打印值:5,按线程:Thread-2
打印值:7,按线程:Thread-1
打印值:9,按线程:Thread-0
打印值:8,按线程:Thread-2

于 2018-10-27T06:47:13.780 回答