以下のコードを試しました。私はこのコードを他の投稿から取りましたが、これは著者によって正しいものです。しかし、実行しようとすると、正確な結果が得られません。
これは主に偶数値と奇数値を順番に印刷するためです。
public class PrintEvenOddTester {
public static void main(String ... args){
Printer print = new Printer(false);
Thread t1 = new Thread(new TaskEvenOdd(print));
Thread t2 = new Thread(new TaskEvenOdd(print));
t1.start();
t2.start();
}
}
class TaskEvenOdd implements Runnable {
int number=1;
Printer print;
TaskEvenOdd(Printer print){
this.print = print;
}
@Override
public void run() {
System.out.println("Run method");
while(number<10){
if(number%2 == 0){
System.out.println("Number is :"+ number);
print.printEven(number);
number+=2;
}
else {
System.out.println("Number is :"+ number);
print.printOdd(number);
number+=2;
}
}
}
}
class Printer {
boolean isOdd;
Printer(boolean isOdd){
this.isOdd = isOdd;
}
synchronized void printEven(int number) {
while(isOdd){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Even:"+number);
isOdd = true;
notifyAll();
}
synchronized void printOdd(int number) {
while(!isOdd){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Odd:"+number);
isOdd = false;
notifyAll();
}
}
誰かがこれを修正するのを手伝ってくれますか?
[〜#〜] edit [〜#〜]期待される結果:奇数:1偶数:2奇数:3偶数:4奇数:5偶数:6奇数:7偶数:8奇数:9
ソリューションを見つけました。この問題の解決策を探している人が参照できます:-)
public class PrintEvenOddTester {
public static void main(String... args) {
Printer print = new Printer();
Thread t1 = new Thread(new TaskEvenOdd(print, 10, false));
Thread t2 = new Thread(new TaskEvenOdd(print, 10, true));
t1.start();
t2.start();
}
}
class TaskEvenOdd implements Runnable {
private int max;
private Printer print;
private boolean isEvenNumber;
TaskEvenOdd(Printer print, int max, boolean isEvenNumber) {
this.print = print;
this.max = max;
this.isEvenNumber = isEvenNumber;
}
@Override
public void run() {
//System.out.println("Run method");
int number = isEvenNumber == true ? 2 : 1;
while (number <= max) {
if (isEvenNumber) {
//System.out.println("Even :"+ Thread.currentThread().getName());
print.printEven(number);
//number+=2;
} else {
//System.out.println("Odd :"+ Thread.currentThread().getName());
print.printOdd(number);
// number+=2;
}
number += 2;
}
}
}
class Printer {
boolean isOdd = false;
synchronized void printEven(int number) {
while (isOdd == false) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Even:" + number);
isOdd = false;
notifyAll();
}
synchronized void printOdd(int number) {
while (isOdd == true) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Odd:" + number);
isOdd = true;
notifyAll();
}
}
これにより、次のような出力が得られます
Odd:1
Even:2
Odd:3
Even:4
Odd:5
Even:6
Odd:7
Even:8
Odd:9
Even:10
これが単一のクラスで動作するようにしたコードです
package com.learn.thread;
public class PrintNumbers extends Thread {
volatile static int i = 1;
Object lock;
PrintNumbers(Object lock) {
this.lock = lock;
}
public static void main(String ar[]) {
Object obj = new Object();
// This constructor is required for the identification of wait/notify
// communication
PrintNumbers odd = new PrintNumbers(obj);
PrintNumbers even = new PrintNumbers(obj);
odd.setName("Odd");
even.setName("Even");
odd.start();
even.start();
}
@Override
public void run() {
while (i <= 10) {
if (i % 2 == 0 && Thread.currentThread().getName().equals("Even")) {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " - "
+ i);
i++;
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (i % 2 == 1 && Thread.currentThread().getName().equals("Odd")) {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " - "
+ i);
i++;
lock.notify();
}
}
}
}
}
出力:
Odd - 1
Even - 2
Odd - 3
Even - 4
Odd - 5
Even - 6
Odd - 7
Even - 8
Odd - 9
Even - 10
Odd - 11
次の非常に単純なJava 8 Runnable Class機能を使用してください
public class MultiThreadExample {
static AtomicInteger atomicNumber = new AtomicInteger(1);
public static void main(String[] args) {
Runnable print = () -> {
while (atomicNumber.get() < 10) {
synchronized (atomicNumber) {
if ((atomicNumber.get() % 2 == 0) && "Even".equals(Thread.currentThread().getName())) {
System.out.println("Even" + ":" + atomicNumber.getAndIncrement());
} else if ((atomicNumber.get() % 2 != 0) && "Odd".equals(Thread.currentThread().getName())) {
System.out.println("Odd" + ":" + atomicNumber.getAndIncrement());
}
}
}
};
Thread t1 = new Thread(print);
t1.setName("Even");
t1.start();
Thread t2 = new Thread(print);
t2.setName("Odd");
t2.start();
}
}
このプログラムは2つの方法で作成できます。
パッケージcom.effectivecorejava; import Java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
//We dont want the even number printed first so the initial permit for this semaphore is 0.
Semaphore evenSemaphore = new Semaphore(0);
//We want to print the odd number first so the initial permit for this semaphore is 1.
Semaphore oddSemaphore = new Semaphore(1);
PrintOddNumber printOddNumber = new PrintOddNumber(evenSemaphore, oddSemaphore);
PrintEvenNumber printEvenNumber = new PrintEvenNumber(evenSemaphore, oddSemaphore);
new Thread(printOddNumber, "Print Odd").start();
new Thread(printEvenNumber, "Print Odd").start();
}
}
class PrintEvenNumber implements Runnable {
Semaphore sempahoreEven;
Semaphore sempahoreOdd;
public PrintEvenNumber(Semaphore sempahoreEven, Semaphore sempahoreOdd) {
super();
this.sempahoreEven = sempahoreEven;
this.sempahoreOdd = sempahoreOdd;
}
@Override
public void run() {
for (int i = 2;; i = i + 2) {
try {
//This will decrement the permit used by the even semaphore to 0.
sempahoreEven.acquire();
System.out.println(i);
//This will increment the permit used by odd semaphore by 1.
sempahoreOdd.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class PrintOddNumber implements Runnable {
Semaphore sempahoreEven;
Semaphore sempahoreOdd;
public PrintOddNumber(Semaphore sempahoreEven, Semaphore sempahoreOdd) {
this.sempahoreEven = sempahoreEven;
this.sempahoreOdd = sempahoreOdd;
}
@Override
public void run() {
for (int i = 1;; i = i + 2) {
try {
//This will decrement the permit used by the odd semaphore to 0.
sempahoreOdd.acquire();
Thread.sleep(1000);
System.out.println(i);
//This will increment the permit used by even semaphore by 1.
sempahoreEven.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private Object lock = new Object();
private volatile boolean isOdd = false;
public void generateEvenNumbers(int number) throws InterruptedException {
synchronized (lock) {
while (isOdd == false)
{
lock.wait();
}
System.out.println(number);
isOdd = false;
lock.notifyAll();
}
}
public void generateOddNumbers(int number) throws InterruptedException {
synchronized (lock) {
while (isOdd == true) {
lock.wait();
}
System.out.println(number);
isOdd = true;
lock.notifyAll();
}
}
このコードも正常に機能します。
class Thread1 implements Runnable {
private static boolean evenFlag = true;
public synchronized void run() {
if (evenFlag == true) {
printEven();
} else {
printOdd();
}
}
public void printEven() {
for (int i = 0; i <= 10; i += 2) {
System.out.println(i+""+Thread.currentThread());
}
evenFlag = false;
}
public void printOdd() {
for (int i = 1; i <= 11; i += 2) {
System.out.println(i+""+Thread.currentThread());
}
evenFlag = true;
}
}
public class OddEvenDemo {
public static void main(String[] args) {
Thread1 t1 = new Thread1();
Thread td1 = new Thread(t1);
Thread td2 = new Thread(t1);
td1.start();
td2.start();
}
}
Lockインターフェースでも同じことができます:
import Java.util.concurrent.locks.Condition;
import Java.util.concurrent.locks.Lock;
import Java.util.concurrent.locks.ReentrantLock;
public class NumberPrinter implements Runnable {
private Lock lock;
private Condition condition;
private String type;
private static boolean oddTurn = true;
public NumberPrinter(String type, Lock lock, Condition condition) {
this.type = type;
this.lock = lock;
this.condition = condition;
}
public void run() {
int i = type.equals("odd") ? 1 : 2;
while (i <= 10) {
if (type.equals("odd"))
printOdd(i);
if (type.equals("even"))
printEven(i);
i = i + 2;
}
}
private void printOdd(int i) {
// synchronized (lock) {
lock.lock();
while (!oddTurn) {
try {
// lock.wait();
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(type + " " + i);
oddTurn = false;
// lock.notifyAll();
condition.signalAll();
lock.unlock();
}
// }
private void printEven(int i) {
// synchronized (lock) {
lock.lock();
while (oddTurn) {
try {
// lock.wait();
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(type + " " + i);
oddTurn = true;
// lock.notifyAll();
condition.signalAll();
lock.unlock();
}
// }
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
Thread odd = new Thread(new NumberPrinter("odd", lock, condition));
Thread even = new Thread(new NumberPrinter("even", lock, condition));
odd.start();
even.start();
}
}
もう1つの質問は、この質問の複製として閉じられました。 「偶数または奇数」の問題を安全に取り除き、wait/notify
次のように構成します。
public class WaitNotifyDemoEvenOddThreads {
/**
* A transfer object, only use with proper client side locking!
*/
static final class LastNumber {
int num;
final int limit;
LastNumber(int num, int limit) {
this.num = num;
this.limit = limit;
}
}
static final class NumberPrinter implements Runnable {
private final LastNumber last;
private final int init;
NumberPrinter(LastNumber last, int init) {
this.last = last;
this.init = init;
}
@Override
public void run() {
int i = init;
synchronized (last) {
while (i <= last.limit) {
while (last.num != i) {
try {
last.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " prints: " + i);
last.num = i + 1;
i += 2;
last.notify();
}
}
}
}
public static void main(String[] args) {
LastNumber last = new LastNumber(0, 10); // or 0, 1000
NumberPrinter odd = new NumberPrinter(last, 1);
NumberPrinter even = new NumberPrinter(last, 0);
new Thread(odd, "o").start();
new Thread(even, "e").start();
}
}
これがこの問題の最も簡単な解決策です。パブリッククラスOddEvenはRunnable {
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 1; i <= 10; i++) {
synchronized (this) {
if (i % 2 == 0 && Thread.currentThread().getName().equals("t2")) {
try {
notifyAll();
System.out.println("Even Thread : " + i);
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else if (i % 2 != 0
&& Thread.currentThread().getName().equals("t1")) {
try {
notifyAll();
System.out.println("Odd Thread : " + i);
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args) {
OddEven obj = new OddEven();
Thread t1 = new Thread(obj, "t1");
Thread t2 = new Thread(obj, "t2");
t1.start();
t2.start();
}
}
import Java.util.concurrent.atomic.AtomicInteger;
public class PrintEvenOddTester {
public static void main(String ... args){
Printer print = new Printer(false);
Thread t1 = new Thread(new TaskEvenOdd(print, "Thread1", new AtomicInteger(1)));
Thread t2 = new Thread(new TaskEvenOdd(print,"Thread2" , new AtomicInteger(2)));
t1.start();
t2.start();
}
}
class TaskEvenOdd implements Runnable {
Printer print;
String name;
AtomicInteger number;
TaskEvenOdd(Printer print, String name, AtomicInteger number){
this.print = print;
this.name = name;
this.number = number;
}
@Override
public void run() {
System.out.println("Run method");
while(number.get()<10){
if(number.get()%2 == 0){
print.printEven(number.get(),name);
}
else {
print.printOdd(number.get(),name);
}
number.addAndGet(2);
}
}
}
class Printer {
boolean isEven;
public Printer() { }
public Printer(boolean isEven) {
this.isEven = isEven;
}
synchronized void printEven(int number, String name) {
while (!isEven) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name+": Even:" + number);
isEven = false;
notifyAll();
}
synchronized void printOdd(int number, String name) {
while (isEven) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name+": Odd:" + number);
isEven = true;
notifyAll();
}
}
Simpler Version in Java 8:
public class EvenOddPrinter {
static boolean flag = true;
public static void main(String[] args) {
Runnable odd = () -> {
for (int i = 1; i <= 10;) {
if(EvenOddPrinter.flag) {
System.out.println(i);
i+=2;
EvenOddPrinter.flag = !EvenOddPrinter.flag;
}
}
};
Runnable even = () -> {
for (int i = 2; i <= 10;) {
if(!EvenOddPrinter.flag) {
System.out.println(i);
i+=2;
EvenOddPrinter.flag = !EvenOddPrinter.flag;
}
}
};
Thread t1 = new Thread(odd, "Odd");
Thread t2 = new Thread(even, "Even");
t1.start();
t2.start();
}
}
以下の簡単なソリューション:-
package com.test;
class MyThread implements Runnable{
@Override
public void run() {
int i=1;
while(true) {
String name=Thread.currentThread().getName();
if(name.equals("task1") && i%2!=0) {
System.out.println(name+"::::"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else if(name.equals("task2") && i%2==0){
System.out.println(name+"::::"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i++;
}
}
public static void main(String[] args) {
MyThread task1=new MyThread();
MyThread task2=new MyThread();
Thread t1=new Thread(task1,"task1");
Thread t2=new Thread(task2,"task2");
t1.start();
t2.start();
}
}
2つのセマフォを使用した実装を次に示します。
偶数のスレッド実行は2を出力し、奇数のSemaを解放して、奇数のスレッドの実行を許可します。
import Java.util.concurrent.Semaphore;
public class EvenOdd {
private final static String ODD = "ODD";
private final static String EVEN = "EVEN";
private final static int MAX_ITERATIONS = 10;
public static class EvenOddThread implements Runnable {
private String mType;
private int mNum;
private Semaphore mMySema;
private Semaphore mOtherSema;
public EvenOddThread(String str, Semaphore mine, Semaphore other) {
mType = str;
mMySema = mine;//new Semaphore(1); // start out as unlocked
mOtherSema = other;//new Semaphore(0);
if(str.equals(ODD)) {
mNum = 1;
}
else {
mNum = 2;
}
}
@Override
public void run() {
for (int i = 0; i < MAX_ITERATIONS; i++) {
mMySema.acquireUninterruptibly();
if (mType.equals(ODD)) {
System.out.println("Odd Thread - " + mNum);
} else {
System.out.println("Even Thread - " + mNum);
}
mNum += 2;
mOtherSema.release();
}
}
}
public static void main(String[] args) throws InterruptedException {
Semaphore odd = new Semaphore(1);
Semaphore even = new Semaphore(0);
System.out.println("Start!!!");
System.out.println();
Thread tOdd = new Thread(new EvenOddThread(ODD,
odd,
even));
Thread tEven = new Thread(new EvenOddThread(EVEN,
even,
odd));
tOdd.start();
tEven.start();
tOdd.join();
tEven.join();
System.out.println();
System.out.println("Done!!!");
}
}
出力は次のとおりです。
Start!!!
Odd Thread - 1
Even Thread - 2
Odd Thread - 3
Even Thread - 4
Odd Thread - 5
Even Thread - 6
Odd Thread - 7
Even Thread - 8
Odd Thread - 9
Even Thread - 10
Odd Thread - 11
Even Thread - 12
Odd Thread - 13
Even Thread - 14
Odd Thread - 15
Even Thread - 16
Odd Thread - 17
Even Thread - 18
Odd Thread - 19
Even Thread - 20
Done!!!
public class ThreadEvenOdd {
static int cnt=0;
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(this) {
while(cnt<101) {
if(cnt%2==0) {
System.out.print(cnt+" ");
cnt++;
}
notifyAll();
}
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(this) {
while(cnt<101) {
if(cnt%2==1) {
System.out.print(cnt+" ");
cnt++;
}
notifyAll();
}
}
}
});
t1.start();
t2.start();
}
}
2つのスレッドを使用して印刷している間、どのスレッドをどのシーケンスで実行するかを予測することはできません。
最初に実行されるので、この状況を克服するには、共有リソースを同期する必要があります。
私の場合は、2つのスレッドがアクセスしようとしている印刷機能です。
class Printoddeven{
public synchronized void print(String msg) {
try {
if(msg.equals("Even")) {
for(int i=0;i<=10;i+=2) {
System.out.println(msg+" "+i);
Thread.sleep(2000);
notify();
wait();
}
} else {
for(int i=1;i<=10;i+=2) {
System.out.println(msg+" "+i);
Thread.sleep(2000);
notify();
wait();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class PrintOdd extends Thread{
Printoddeven oddeven;
public PrintOdd(Printoddeven oddeven){
this.oddeven=oddeven;
}
public void run(){
oddeven.print("ODD");
}
}
class PrintEven extends Thread{
Printoddeven oddeven;
public PrintEven(Printoddeven oddeven){
this.oddeven=oddeven;
}
public void run(){
oddeven.print("Even");
}
}
public class mainclass
{
public static void main(String[] args) {
Printoddeven obj = new Printoddeven();//only one object
PrintEven t1=new PrintEven(obj);
PrintOdd t2=new PrintOdd(obj);
t1.start();
t2.start();
}
}
次のコードを使用して、2つの匿名スレッドクラスを作成して出力を取得できます。
package practice;
class Display {
boolean isEven = false;
synchronized public void printEven(int number) throws InterruptedException {
while (isEven)
wait();
System.out.println("Even : " + number);
isEven = true;
notify();
}
synchronized public void printOdd(int number) throws InterruptedException {
while (!isEven)
wait();
System.out.println("Odd : " + number);
isEven = false;
notify();
}
}
public class OddEven {
public static void main(String[] args) {
// TODO Auto-generated method stub
final Display disp = new Display();
new Thread() {
public void run() {
int num = 0;
for (int i = num; i <= 10; i += 2) {
try {
disp.printEven(i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
new Thread() {
public void run() {
int num = 1;
for (int i = num; i <= 10; i += 2) {
try {
disp.printOdd(i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
}
}
私はここにあるコードのほとんどを理解できなかったので、自分で書いた。たぶん私のような人に役立つだろう:
注:これは、偶数と奇数の個別の印刷方法を使用しません。 1つのメソッドprint()がすべてを実行します。
public class test {
private static int START_INT = 1;
private static int STOP_INT = 10;
private static String THREAD_1 = "Thread A";
private static String THREAD_2 = "Thread B";
public static void main(String[] args) {
SynchronizedRepository syncRep = new SynchronizedRepository(START_INT,STOP_INT);
Runnable r1 = new EvenOddWorker(THREAD_1,syncRep);
Runnable r2 = new EvenOddWorker(THREAD_2,syncRep);
Thread t1 = new Thread(r1, THREAD_1);
Thread t2 = new Thread(r2, THREAD_2);
t1.start();
t2.start();
}
}
public class SynchronizedRepository {
private volatile int number;
private volatile boolean isSlotEven;
private int startNumber;
private int stopNumber;
public SynchronizedRepository(int startNumber, int stopNumber) {
super();
this.number = startNumber;
this.isSlotEven = startNumber%2==0;
this.startNumber = startNumber;
this.stopNumber = stopNumber;
}
public synchronized void print(String threadName) {
try {
for(int i=startNumber; i<=stopNumber/2; i++){
if ((isSlotEven && number % 2 == 0)||
(!isSlotEven && number % 2 != 0)){
System.out.println(threadName + " "+ number);
isSlotEven = !isSlotEven;
number++;
}
notifyAll();
wait();
}
notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class EvenOddWorker implements Runnable {
private String threadName;
private SynchronizedRepository syncRep;
public EvenOddWorker(String threadName, SynchronizedRepository syncRep) {
super();
this.threadName = threadName;
this.syncRep = syncRep;
}
@Override
public void run() {
syncRep.print(threadName);
}
}
public class OddEven implements Runnable {
public int count = 0;
@Override
public void run() {
try {
increment();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
synchronized void increment() throws Exception {
while(true) {
if(count<10) {
count++;
System.out.println(Thread.currentThread().getName()+" " +count);
notify();
wait();
}else {
break;
}
}
}
public static void main(String[] args) {
OddEven n1 = new OddEven();
Thread r1 = new Thread(n1);
Thread r2 = new Thread(n1);
r1.start();
r2.start();
}
}
public class Main {
public static void main(String[] args) throws Exception{
int N = 100;
PrintingThread oddNumberThread = new PrintingThread(N - 1);
PrintingThread evenNumberThread = new PrintingThread(N);
oddNumberThread.start();
// make sure that even thread only start after odd thread
while (!evenNumberThread.isAlive()) {
if(oddNumberThread.isAlive()) {
evenNumberThread.start();
} else {
Thread.sleep(100);
}
}
}
}
class PrintingThread extends Thread {
private static final Object object = new Object(); // lock for both threads
final int N;
// N determines whether given thread is even or odd
PrintingThread(int N) {
this.N = N;
}
@Override
public void run() {
synchronized (object) {
int start = N % 2 == 0 ? 2 : 1; // if N is odd start from 1 else start from 0
for (int i = start; i <= N; i = i + 2) {
System.out.println(i);
try {
object.notify(); // will notify waiting thread
object.wait(); // will make current thread wait
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
package pkgscjp;
public class OddPrint implements Runnable {
public static boolean flag = true;
public void run() {
for (int i = 1; i <= 99;) {
if (flag) {
System.out.println(i);
flag = false;
i = i + 2;
}
}
}
}
package pkgscjp;
public class EvenPrint implements Runnable {
public void run() {
for (int i = 2; i <= 100;) {
if (!OddPrint.flag) {
System.out.println(i);
OddPrint.flag = true;
i = i + 2;
}
}
}
}
package pkgscjp;
public class NaturalNumberThreadMain {
public static void main(String args[]) {
EvenPrint ep = new EvenPrint();
OddPrint op = new OddPrint();
Thread te = new Thread(ep);
Thread to = new Thread(op);
to.start();
te.start();
}
}
Clean実装を参照してください
public class PrintOddEvenByTwoThreads {
static int number = 1;
static Thread odd;
static Thread even;
static int max = 10;
static class OddThread extends Thread {
@Override
public void run() {
while (number <= max) {
if (number % 2 == 1) {
System.out.println(Thread.currentThread() + "" + number++);
} else {
synchronized (odd) {
synchronized (even) {
even.notify();
}
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
static class EvenThread extends Thread {
@Override
public void run() {
while (number <= max) {
if (number % 2 == 0) {
System.out.println(Thread.currentThread() + "" + number++);
} else {
synchronized (even) {
synchronized (odd) {
odd.notify();
}
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public static void main(String[] args) throws InterruptedException {
odd = new OddThread();
even = new EvenThread();
odd.start();
even.start();
}
}
package com.example;
public class MyClass {
static int mycount=0;
static Thread t;
static Thread t2;
public static void main(String[] arg)
{
t2=new Thread(new Runnable() {
@Override
public void run() {
System.out.print(mycount++ + " even \n");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(mycount>25)
System.exit(0);
run();
}
});
t=new Thread(new Runnable() {
@Override
public void run() {
System.out.print(mycount++ + " odd \n");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(mycount>26)
System.exit(0);
run();
}
});
t.start();
t2.start();
}
}
1-番号は1で初期化され、isOdd
フラグはfalseに設定されます。 isOdd
をtrueに設定します
2-インクリメントは1(2ではなく)でなければなりません。つまりnumber+=1
;
これが私の問題の解決策です。 Runnable
を実装する2つのクラスがあり、1つは奇数のシーケンスを出力し、もう1つは偶数を出力します。ロックに使用するObject
のインスタンスがあります。 2つのクラスを同じオブジェクトで初期化します。 2つのクラスのrunメソッド内に_synchronized block
_があります。ループ内では、各メソッドが番号の1つを出力し、他のスレッドに通知し、同じオブジェクトのロックを待機してから、同じメソッドを待機します。もう一度ロックします。
クラス:
_public class PrintEven implements Runnable{
private Object lock;
public PrintEven(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
for (int i = 2; i <= 10; i+=2) {
System.out.println("EVEN:="+i);
lock.notify();
try {
//if(i!=10) lock.wait();
lock.wait(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class PrintOdd implements Runnable {
private Object lock;
public PrintOdd(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
for (int i = 1; i <= 10; i+=2) {
System.out.println("ODD:="+i);
lock.notify();
try {
//if(i!=9) lock.wait();
lock.wait(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class PrintEvenOdd {
public static void main(String[] args){
Object lock = new Object();
Thread thread1 = new Thread(new PrintOdd(lock));
Thread thread2 = new Thread(new PrintEven(lock));
thread1.start();
thread2.start();
}
}
_
この例の上限は10です。奇数のスレッドが9を出力するか、偶数のスレッドが10を出力すると、待機するスレッドは不要になります。したがって、1つの_if-block
_を使用して処理できます。または、オーバーロードされたwait(long timeout)
メソッドを使用して、待機をタイムアウトにすることができます。ただし、ここで1つの欠陥があります。このコードでは、どのスレッドが最初に実行を開始するかを保証できません。
ロックと条件を使用する別の例
_import Java.util.concurrent.locks.Condition;
import Java.util.concurrent.locks.Lock;
import Java.util.concurrent.locks.ReentrantLock;
public class LockConditionOddEven {
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Condition evenCondition = lock.newCondition();
Condition oddCondition = lock.newCondition();
Thread evenThread = new Thread(new EvenPrinter(10, lock, evenCondition, oddCondition));
Thread oddThread = new Thread(new OddPrinter(10, lock, evenCondition, oddCondition));
oddThread.start();
evenThread.start();
}
static class OddPrinter implements Runnable{
int i = 1;
int limit;
Lock lock;
Condition evenCondition;
Condition oddCondition;
public OddPrinter(int limit) {
super();
this.limit = limit;
}
public OddPrinter(int limit, Lock lock, Condition evenCondition, Condition oddCondition) {
super();
this.limit = limit;
this.lock = lock;
this.evenCondition = evenCondition;
this.oddCondition = oddCondition;
}
@Override
public void run() {
while( i <=limit) {
lock.lock();
System.out.println("Odd:"+i);
evenCondition.signal();
i+=2;
try {
oddCondition.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
static class EvenPrinter implements Runnable{
int i = 2;
int limit;
Lock lock;
Condition evenCondition;
Condition oddCondition;
public EvenPrinter(int limit) {
super();
this.limit = limit;
}
public EvenPrinter(int limit, Lock lock, Condition evenCondition, Condition oddCondition) {
super();
this.limit = limit;
this.lock = lock;
this.evenCondition = evenCondition;
this.oddCondition = oddCondition;
}
@Override
public void run() {
while( i <=limit) {
lock.lock();
System.out.println("Even:"+i);
i+=2;
oddCondition.signal();
try {
evenCondition.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
_
}
public class OddAndEvenThreadProblems {
private static Integer i = 0;
public static void main(String[] args) {
new EvenClass().start();
new OddClass().start();
}
public static class EvenClass extends Thread {
public void run() {
while (i < 10) {
synchronized (i) {
if (i % 2 == 0 ) {
try {
Thread.sleep(1000);
System.out.println(" EvenClass " + i);
i = i + 1;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
public static class OddClass extends Thread {
@Override
public void run() {
while (i < 10) {
synchronized (i) {
if (i % 2 == 1) {
try {
Thread.sleep(1000);
System.out.println(" OddClass " + i);
i = i + 1;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
}
OUTPUT will be :-
EvenClass 0
OddClass 1
EvenClass 2
OddClass 3
EvenClass 4
OddClass 5
EvenClass 6
OddClass 7
EvenClass 8
OddClass 9
これはLockとConditionを使用して実現できます。
import Java.util.concurrent.locks.Condition;
import Java.util.concurrent.locks.Lock;
import Java.util.concurrent.locks.ReentrantLock;
public class EvenOddThreads {
public static void main(String[] args) throws InterruptedException {
Printer p = new Printer();
Thread oddThread = new Thread(new PrintThread(p,false),"Odd :");
Thread evenThread = new Thread(new PrintThread(p,true),"Even :");
oddThread.start();
evenThread.start();
}
}
class PrintThread implements Runnable{
Printer p;
boolean isEven = false;
PrintThread(Printer p, boolean isEven){
this.p = p;
this.isEven = isEven;
}
@Override
public void run() {
int i = (isEven==true) ? 2 : 1;
while(i < 10 ){
if(isEven){
p.printEven(i);
}else{
p.printOdd(i);
}
i=i+2;
}
}
}
class Printer{
boolean isEven = true;
Lock lock = new ReentrantLock();
Condition condEven = lock.newCondition();
Condition condOdd = lock.newCondition();
public void printEven(int no){
lock.lock();
while(isEven==true){
try {
condEven.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() +no);
isEven = true;
condOdd.signalAll();
lock.unlock();
}
public void printOdd(int no){
lock.lock();
while(isEven==false){
try {
condOdd.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() +no);
isEven = false;
condEven.signalAll();
lock.unlock();
}
}
パブリッククラスソリューション{
static class NumberGenerator{
private static volatile boolean printEvenNumber = false;
public void printEvenNumber(int i) {
synchronized (this) {
if(!printEvenNumber) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
printEvenNumber = !printEvenNumber;
notify();
}
}
public void printOddNumber(int i ) {
synchronized (this) {
if(printEvenNumber) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
printEvenNumber = !printEvenNumber;
notify();
}
}
}
static class OddNumberGenerator implements Runnable{
private NumberGenerator numberGenerator;
public OddNumberGenerator(NumberGenerator numberGenerator) {
this.numberGenerator = numberGenerator;
}
@Override
public void run() {
for(int i = 1; i <100; i = i + 2) {
numberGenerator.printOddNumber(i);
}
}
}
static class EvenNumberGenerator implements Runnable {
private NumberGenerator numberGenerator;
public EvenNumberGenerator(NumberGenerator numberGenerator) {
this.numberGenerator = numberGenerator;
}
@Override
public void run() {
for (int i = 2; i <= 100; i = i + 2) {
numberGenerator.printEvenNumber(i);
}
}
}
public static void main(String[] args) {
NumberGenerator ng = new NumberGenerator();
OddNumberGenerator oddNumberGenerator = new OddNumberGenerator(ng);
EvenNumberGenerator evenNumberGenerator = new EvenNumberGenerator(ng);
new Thread(oddNumberGenerator).start();
new Thread(evenNumberGenerator).start();
}
}
単一クラスを使用した実用的なソリューション
package com.fursa.threads;
public class PrintNumbers extends Thread {
Object lock;
PrintNumbers(Object lock) {
this.lock = lock;
}
public static void main(String ar[]) {
Object obj = new Object();
// This constructor is required for the identification of wait/notify
// communication
PrintNumbers odd = new PrintNumbers(obj);
PrintNumbers even = new PrintNumbers(obj);
odd.setName("Odd");
even.setName("Even");
even.start();
odd.start();
}
@Override
public void run() {
for(int i=0;i<=100;i++) {
synchronized (lock) {
if (Thread.currentThread().getName().equals("Even")) {
if(i % 2 == 0 ){
System.out.println(Thread.currentThread().getName() + " - "+ i);
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else if (i % 2 != 0 ) {
lock.notify();
}
}
if (Thread.currentThread().getName().equals("Odd")) {
if(i % 2 == 1 ){
System.out.println(Thread.currentThread().getName() + " - "+ i);
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else if (i % 2 != 1 ) {
lock.notify();
}
}
}
}
}
}
package example;
public class PrintSeqTwoThreads {
public static void main(String[] args) {
final Object mutex = new Object();
Thread t1 = new Thread() {
@Override
public void run() {
for (int j = 0; j < 10;) {
synchronized (mutex) {
System.out.println(Thread.currentThread().getName() + " " + j);
j = j + 2;
mutex.notify();
try {
mutex.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
for (int j = 1; j < 10;) {
synchronized (mutex) {
System.out.println(Thread.currentThread().getName() + " " + j);
j = j + 2;
mutex.notify();
try {
mutex.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
t1.start();
t2.start();
}
}
次のコードを使用して、必要なメッセージとともに適切な順序で奇数と偶数を印刷してください。
package practice;
class Test {
private static boolean oddFlag = true;
int count = 1;
private void oddPrinter() {
synchronized (this) {
while(true) {
try {
if(count < 10) {
if(oddFlag) {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + ": " + count++);
oddFlag = !oddFlag;
notifyAll();
}
else {
wait();
}
}
else {
System.out.println("Odd Thread finished");
notify();
break;
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void evenPrinter() {
synchronized (this) {
while (true) {
try {
if(count < 10) {
if(!oddFlag) {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + ": " + count++);
oddFlag = !oddFlag;
notify();
}
else {
wait();
}
}
else {
System.out.println("Even Thread finished");
notify();
break;
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException{
final Test test = new Test();
Thread t1 = new Thread(new Runnable() {
public void run() {
test.oddPrinter();
}
}, "Thread 1");
Thread t2 = new Thread(new Runnable() {
public void run() {
test.evenPrinter();
}
}, "Thread 2");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Main thread finished");
}
}
シンプルなソリューション:)
package com.code.threads;
public class PrintOddEven extends Thread {
private Object lock;
static volatile int count = 1;
PrintOddEven(Object lock) {
this.lock = lock;
}
@Override
public void run () {
while(count <= 10) {
if (count % 2 == 0) {
synchronized(lock){
System.out.println("Even - " + count);
++count;
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
synchronized(lock){
System.out.println("Odd - " + count);
++count;
lock.notify();
}
}
}
}
public static void main(String[] args) {
Object obj = new Object();
PrintOddEven even = new PrintOddEven(obj);
PrintOddEven odd = new PrintOddEven(obj);
even.start();
odd.start();
}
}
奇数の偶数を印刷するクラス
public class PrintOddEven implements Runnable {
private int max;
private int number;
public PrintOddEven(int max_number,int number) {
max = max_number;
this.number = number;
}
@Override
public void run() {
while(number<=max)
{
if(Thread.currentThread().getName().equalsIgnoreCase("odd"))
{
try {
printOdd();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
try {
printEven();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public synchronized void printOdd() throws InterruptedException
{
if(number%2==0)
{
wait();
}
System.out.println(number+Thread.currentThread().getName());
number++;
notifyAll();
}
public synchronized void printEven() throws InterruptedException
{
if(number%2!=0)
{
wait();
}
System.out.println(number+Thread.currentThread().getName());
number++;
notifyAll();
}
}
ドライバープログラム
public class OddEvenThread {
public static void main(String[] args) {
PrintOddEven printer = new PrintOddEven(10,1);
Thread thread1 = new Thread(printer,"odd");
Thread thread2 = new Thread (printer,"even");
thread1.start();
thread2.start();
}
}
提供されているソリューションには不必要に追加されたものがあり、セマフォを最大限に使用していないと思います。これが私のソリューションです。
package com.test.threads;
import Java.util.concurrent.Semaphore;
public class EvenOddThreadTest {
public static int MAX = 100;
public static Integer number = new Integer(0);
//Unlocked state
public Semaphore semaphore = new Semaphore(1);
class PrinterThread extends Thread {
int start = 0;
String name;
PrinterThread(String name ,int start) {
this.start = start;
this.name = name;
}
@Override
public void run() {
try{
while(start < MAX){
// try to acquire the number of semaphore equal to your value
// and if you do not get it then wait for it.
semaphore.acquire(start);
System.out.println(name + " : " + start);
// prepare for the next iteration.
start+=2;
// release one less than what you need to print in the next iteration.
// This will release the other thread which is waiting to print the next number.
semaphore.release(start-1);
}
} catch(InterruptedException e){
}
}
}
public static void main(String args[]) {
EvenOddThreadTest test = new EvenOddThreadTest();
PrinterThread a = test.new PrinterThread("Even",1);
PrinterThread b = test.new PrinterThread("Odd", 2);
try {
a.start();
b.start();
} catch (Exception e) {
}
}
}
package programs.multithreading;
public class PrintOddEvenNoInSequence {
final int upto;
final PrintOddEvenNoInSequence obj;
volatile boolean oddFlag,evenFlag;
public PrintOddEvenNoInSequence(int upto){
this.upto = upto;
obj = this;
oddFlag = true;
evenFlag = false;
}
void printInSequence(){
Thread odd = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 1; i <= upto; i = i + 2){
synchronized (obj) {
while(!oddFlag){
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Odd:"+i);
oddFlag = false;
evenFlag = true;
obj.notify();
}
}
}
});
Thread even = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 2; i <= upto; i = i + 2){
synchronized (obj) {
while(!evenFlag){
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Even:"+i);
oddFlag = true;
evenFlag = false;
obj.notify();
}
}
}
});
odd.start();
even.start();
}
public static void main(String[] args) {
new PrintOddEvenNoInSequence(100).printInSequence();
}
}
以下は、待機と通知メカニズムを交互に使用して、奇数でも奇数でも印刷する作業コードです。数字の制限を1〜50に制限しています。
public class NotifyTest {
Object ob=new Object();
public static void main(String[] args) {
// TODO Auto-generated method stub
NotifyTest nt=new NotifyTest();
even e=new even(nt.ob);
odd o=new odd(nt.ob);
Thread t1=new Thread(e);
Thread t2=new Thread(o);
t1.start();
t2.start();
}
}
class even implements Runnable
{
Object lock;
int i=2;
public even(Object ob)
{
this.lock=ob;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(i<=50)
{
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Even Thread Name-->>" + Thread.currentThread().getName() + "Value-->>" + i);
i=i+2;
}
}
}
class odd implements Runnable
{
Object lock;
int i=1;
public odd(Object ob)
{
this.lock=ob;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(i<=49)
{
synchronized (lock) {
System.out.println("Odd Thread Name-->>" + Thread.currentThread().getName() + "Value-->>" + i);
i=i+2;
lock.notify();
}
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}