两个线程按顺序交替输出1-100
继承Thread类,实现Runnable接口均可
方法一:使用synchronized关键字
public class PrintNumber extends Thread {
private static int cnt = 0;
private int id; // 线程编号
public PrintNumber(int id) {
this.id = id;
}
@Override
public void run() {
while (cnt <= 100) {
if (cnt%2 == id) {
synchronized (PrintNumber.class) {
cnt++;
System.out.println("thread_" + id + " num:" + cnt);
}
}
}
}
public static void main(String[] args) {
Thread thread0 = new PrintNumber(0);
Thread thread1 = new PrintNumber(1);
thread0.start();
thread1.start();
}
}
方法二:使用synchronized关键字,wait和notify
public class PrintNumber extends Thread {
private static int cnt = 0;
private int id; // 线程编号
public PrintNumber(int id) {
this.id = id;
}
@Override
public void run() {
while (cnt <= 100) {
synchronized (PrintNumber.class) {
cnt++;
System.out.println("thread_" + id + " num:" + cnt);
PrintNumber.class.notify();
try {
PrintNumber.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Thread thread0 = new PrintNumber(0);
Thread thread1 = new PrintNumber(1);
thread0.start();
thread1.start();
}
}
public class Test {
public static void main(String[] args){
Number number = new Number();
Thread t1 = new Thread(number);
Thread t2 = new Thread(number);
t1.setName("线程1");
t2.setName("线程2");
t1.start();
t2.start();
}
}
class Number implements Runnable{
private int number = 1;
@Override
public void run(){
while(number <= 100){
synchronized(this){
System.out.println(number);
number++;
notify();
try{
if(number <= 100){
wait();
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
方法三:使用ReentrantLock
把synchronized换成lock,然后把wait和notify换成Condition的signal和await
public class PrintNumber extends Thread {
private static Lock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
private int id;
private static int cnt = 0;
public PrintNumber(int id) {
this.id = id;
}
private static void print(int id) {
}
@Override
public void run() {
while (cnt <= 100) {
lock.lock();
System.out.println("thread_" + id + " num:" + cnt);
cnt++;
condition.signal();
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
}
}
public static void main(String[] args) {
Thread thread0 = new PrintNumber(0);
Thread thread1 = new PrintNumber(1);
thread0.start();
thread1.start();
}
}
方法四:不使用锁,利用volatile实现
//两个线程,一个打印奇数,一个打印偶数
public class OneToHundred{
static volatile int flag = 0;
public static void main(String[] args){
new Thread(new Task1(),"A").start();
new Thread(new Task2(),"B").start();
}
}
class Task1 implements Runnable{
@Override
public void run(){
int i = -2;
while(i<=99){
if(OneToHundred.flag == 0){
i+=2;
System.out.println("a:" + i);
OneToHundred.flag = 1;
}
}
}
}
class Task2 implements Runnable{
@Override
public void run(){
int i = -1;
while(i<=98){
if(OneToHundred.flag == 1){
i+=2;
System.out.println("b:" + i);
OneToHundred.flag = 0;
}
}
}
}
方法五:使用AtomicInteger
public class PrintNumber extends Thread {
private static AtomicInteger cnt = new AtomicInteger();
private int id;
public PrintNumber(int id) {
this.id = id;
}
@Override
public void run() {
while (cnt.get() <= 100) {
if (cnt.get()%2 == id) {
System.out.println("thread_" + id + " num:" + cnt.get());
cnt.incrementAndGet();
}
}
}
public static void main(String[] args) {
Thread thread0 = new PrintNumber(0);
Thread thread1 = new PrintNumber(1);
thread0.start();
thread1.start();
}
}
扩展问题
- 如果是三个线程交替输出呢?
解析:三个线程的解法可以使用while (cnt%3 == id)的方式实现忙等,但简单的唤醒+等待的方式必然不适用了, 没有判断的synchronized必然实现不了,java Object的notify和wait方法只能唤醒全部线程,然后另外两个线程输出前都需要额外判断下是否轮到自己输出了。这时候lock中condition的优势就体现出来了,它可以通过设置不同的condition来实现不同线程的精确唤醒。
public class Test {
volatile int i = 1;
public static void main(String[] args) throws Exception {
Test obj = new Test();
Runnable runnable = new Runnable() {
@Override
public void run() {
while (obj.i <= 100) {
// 上锁当前对象
synchronized (this) {
// 唤醒另一个线程
notifyAll();
if (obj.i == 101) {
return;
}
int i = new Integer(Thread.currentThread().getName());
if (obj.i % 3 == i) {
System.out.println("Thread " + Thread.currentThread().getName() + " " + obj.i++);
}
if(obj.i % 3==1){
System.out.println("==========");
}
try {
if (obj.i == 101) {
notifyAll();
return;
} else {
// 释放掉锁
wait();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
};
// 启动多个线程(想创建几个就创建几个)
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
Thread t3 = new Thread(runnable);
t1.setName("1");
t2.setName("2");
t3.setName("0");
t1.start();
t2.start();
t3.start();
}
}
public static void main(String[] args){
Thread thread0 = new PrintNumber(0);
Thread thread1 = new PrintNumber(1);
Thread thread2 = new PrintNumber(2);
thread0.start();
thread1.start();
thread2.start();
}
class PrintNumber extends Thread{
private static int cnt = 0;
private int id; // 线程编号
public PrintNumber(int id) {
this.id = id;
}
@Override
public void run() {
while (cnt < 100) {
if (cnt % 3 == id) {
synchronized (PrintNumber.class) {
cnt++;
System.out.println("thread_" + id + " num:" + cnt);
}
}
}
}
}