Java并发编程的一些基础知识

(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

打印出的结果是这样的,这跟加没加yield产生的效果貌似是雷同的,仔细分析下,当某个线程执行了run后就出让cpu,这跟其他线程继续执行run一样的效果。

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

,输出的结果是正确的。









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值