有两个线程一个打印{1,3,5,7,9}。另一个打印{2,4,6,8,10}
我想打印{1,2,3,4,5,6,7 ...}
package com.oddnumber.threading;
public class NumberPrint implements Runnable {
int number=1;
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("even" + number);
isOdd = false;
lock.notifyAll();
}
}
public void generateOddNumbers(int number) throws InterruptedException {
synchronized (lock) {
while (isOdd == true) {
lock.wait();
}
System.out.println("odd" + number);
isOdd = true;
lock.notifyAll();
}
}
@Override
public void run() {
while(true) {
if(number%2 == 0) {
try {
generateEvenNumbers(number);
number++;
Thread.sleep(1112);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
try {
generateOddNumbers(number);
number++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
我用以下方法执行了它:
package com.oddnumber.threading;
public class Test
{
public static void main(String[] args) {
NumberPrint n1 = new NumberPrint();
NumberPrint n2 = new NumberPrint();
new Thread(n1).start();
new Thread(n2).start();
}
}
输出:
1
1
2
2
3
3
4
4
5
5
6
6
7
8
7
8
9
9
10
每个数字都打印两次,但为什么两个线程之间不共享数字变量?
答案 0 :(得分:4)
NumberPrint类的每个实例都有自己的lock对象实例。在两个不同的实例上使用synchronized将不起作用。方法必须使用相同的对象。一种方法是使用main()方法创建一个对象的实例并将其传递给NumberPrint构造函数,这样只有一个实例可以使用所有方法进行同步。
答案 1 :(得分:0)
首先,您需要在NumberPrint
static
(可能还有static volatile
)中创建变量,以便在两个线程之间共享它们。这应该针对number
,lock
和isOdd
进行。如果这就是你所做的一切,你的输出将是{1,2,1,4,5,6,7,8 ......},因为两个线程都尽可能快地读取number
他们开始运行,没有任何同步。最好的解决方案似乎是确保generateEvenNumbers
和generateOddNumbers
在同步后读取共享的number
- 这意味着删除number
参数到这些例程,以及然后,当他们阅读number
时,它将是共享的。
答案 2 :(得分:0)
正如NormR所说,两个线程必须共享相同的锁,例如:
public class Main {
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
Thread evenThread = new Thread(new GeneratorHandler(lock, new EvenGenerator()));
Thread oddThread = new Thread(new GeneratorHandler(lock, new OddGenerator()));
oddThread.start();
Thread.sleep(500);
evenThread.start();
}
}
public interface Generator {
public int generate();
}
public class EvenGenerator implements Generator {
int n = 0;
@Override
public int generate() {
return n += 2;
}
}
public class OddGenerator implements Generator {
int n = -1;
@Override
public int generate() {
return n += 2;
}
}
public class GeneratorHandler implements Runnable {
private Object lock;
private Generator generator;
public GeneratorHandler(Object lock, Generator generator) {
this.lock = lock;
this.generator = generator;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(lock){
System.out.println(generator.generate());
}
}
}
}
答案 3 :(得分:0)
public class PrintOnetoTen {
public static void main(String[] args) {
SharedPrinter sp = new SharedPrinter();
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(new EvenNumberProducer(sp, 10));
executor.submit(new OddNumberProducer(sp , 10));
executor.shutdown();
}
}
class SharedPrinter {
Semaphore semEven = new Semaphore(0);
Semaphore semOdd = new Semaphore(1);
public void printEvenNumber(int num) {
try {
semEven.acquire();
}catch(InterruptedException exception) {
}
System.out.println("Thread 2 - Number : " +num);
semOdd.release();
}
public void printOddNumber(int num) {
try {
semOdd.acquire();
}catch(InterruptedException exception) {
}
System.out.println("Thread 1 - Number : " +num);
semEven.release();
}
}
class EvenNumberProducer implements Runnable {
SharedPrinter sp;
int index;
EvenNumberProducer(SharedPrinter sp , int index) {
this.sp = sp;
this.index = index;
}
@Override
public void run() {
for(int i = 2 ; i <= index ; i = i + 2 ) {
sp.printEvenNumber(i);
}
}
}
class OddNumberProducer implements Runnable{
SharedPrinter sp;
int index;
OddNumberProducer(SharedPrinter sp , int index) {
this.sp = sp;
this.index = index;
}
@Override
public void run() {
for(int i = 1 ; i <= index ; i = i + 2) {
sp.printOddNumber(i);
}
}
}
程序输出为:
Thread 1 - Number : 1
Thread 2 - Number : 2
Thread 1 - Number : 3
Thread 2 - Number : 4
Thread 1 - Number : 5
Thread 2 - Number : 6
Thread 1 - Number : 7
Thread 2 - Number : 8
Thread 1 - Number : 9
Thread 2 - Number : 10