(1)yield关键字,是让出自己占用的cpu资源,让给其他ready线程使用
class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
public void run() {
for (;;) {
System.out.println(name + ": hello world");
yield();
}
}
}
public class Main3 {
public static void main(String [] args) {
MyThread t1 = new MyThread("thread1");
MyThread t2 = new MyThread("thread2");
t1.start(); t2.start();
}
}
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
thread2: hello world
thread1: hello world
(2)public final void join(),字面上的意思是 联合,这个方法在c++,perl等脚本语言中常用到,用于拼接字符串等操作,先看下面一段代码:
public class JoinMethodTest implements Runnable {
public static int a = 0;
public void run(){
for(int i=0;i<5;i++)
a = a+i;
}
public static void main(String[] args) {
JoinMethodTest test = new JoinMethodTest();
Thread t = new Thread(test);
t.start();
System.out.println(a);
}
}
猜猜这样的输出结果是怎样的,一定是10吗?不一定是,这里的输出结果是0,是不是一定是0,也不一定,Java多线程就是这样,为什么呢?因为进入到main线程后,在创建Thread t并开启线程的时候,这里有一个时间间隔,cpu不会停在这里等它分配资源并加入到等待队列中去,这个时候它会去执行System.out.println(a),所以结果就是0,那怎么样让他输出正确的结果呢,将这个线程的执行并入到主线程中,这样整个代码就是按照顺序执行了,等到t.start执行完毕后再去执行剩下的System.out.println(a)
public class JoinMethodTest implements Runnable {
public static int a = 0;
public void run(){
for(int i=0;i<5;i++)
a = a+i;
}
public static void main(String[] args) {
JoinMethodTest test = new JoinMethodTest();
Thread t = new Thread(test);
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(a);
}
}
这样结果就是10了,所以从这里可以看出 join 在多线程编程中的含义就是 将当前线程加入到main线程中(更准确的说法是将两个交替执行的线程合并为顺序执行的线程),执行的顺序就是调用这个方法的线程先执行完毕 然后其他的线程执行。
来看段 join 的jdk源码实现:
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
从上面可以看出,join可以带时间参数的,表示需要在多久执行完毕,否则直接die,如果这个调用join的线程是存活的,那么其他线程可以拿到Thread t对象的锁,调用wait让main线程等着,直到这个线程执行完毕唤醒了main线程才能继续执行。
下面来看这样一个问题:
/**
*
* 线程之间协作打印出ABC,按照顺序先第一个线程打印A,然后第二个线程打印B,最后一个线程打印C
*
*/
public class TheLastQuestion {
boolean aFlag = true, bFlag = false, cFlag = false; // 标志是否论到这个线程执行任务
public synchronized void printA() throws InterruptedException {
while (!aFlag) {
this.wait();
}
System.out.print("A");
bFlag = true;// 轮到A打印了
aFlag = false;
cFlag = false;
notifyAll();
}
public synchronized void printB() throws InterruptedException {
while (!bFlag) {
this.wait();
}
System.out.print("B");
cFlag = true;// 轮到B打印了
aFlag = false;//这里一定要改回标志位,因为其他线程持有的这个标志位也许是true,当一旦进入到那个持有true的线程,就会乱序
bFlag = false;
notifyAll();
}
public synchronized void printC() throws InterruptedException {
while (!cFlag) {
this.wait();
}
System.out.print("C");
aFlag = true;// 轮到c打印了
bFlag = false;
cFlag = false;
notifyAll();
}
public static void main(String args[]) throws InterruptedException {
TheLastQuestion theLastQuestion = new TheLastQuestion();
Thread aClass = new InnerClass('A', theLastQuestion);
Thread bClass = new InnerClass('B', theLastQuestion);
Thread cClass = new InnerClass('C', theLastQuestion);
aClass.start();
bClass.start();
cClass.start();
// bClass.join();
// cClass.join();
}
}
class InnerClass extends Thread {
private char c;
TheLastQuestion this$0;
public InnerClass(char c, TheLastQuestion theLastQuestion1) {
this.c = c;
this.this$0 = theLastQuestion1;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
if (c == 'A')
this$0.printA();
else if (c == 'B')
this$0.printB();
else
this$0.printC();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}