Java线程的基本使用

先声明一下,本文参考了何红辉著《Android开发进阶 从小工到专家》第三章节:“Android中的多线程”内容,故逻辑可能会出现一些相似之处。

在java中,多线程使用的成本是相对较低的,其中有两种常见的使用方法:

第一种,直接重写Thread的run()方法,然后启动线程:


public class ThreadDemo {
	
	public static void main(String[] args) {
		System.out.println("主线程启动");
		new Thread(){
			@Override
			public void run(){
				System.out.println(Thread.currentThread().getName()+"正在运行");
			}
		}.start();
		System.out.println("主线程结束");
	}

}

第二种,在new Thread的时候传入一个已经实现run()方法的Runnable实例对象,Thread会执行其对应的run方法:

public class ThreadDemo {
	
	public static void main(String[] args) {
		System.out.println("主线程启动");
		new Thread(new Runnable() {
			@Override
			public void run() {
	System.out.println(Thread.currentThread().getName()+"正在运行");
			}
		}).start();
		System.out.println("主线程结束");
	}

}

事实上,这两种实现方式基本上没有任何区别,因为Thread本来就是一个实现了Runnable接口的一个类(class java.lang.Thread implements java.lang.Runnable),线程最终执行的任务只是Runnable,而非ThreadThread仅仅是对Runnable的封装。

   关于线程函数:

   wait():当一个线程执行此方法时,线程会释放对象锁,让其他资源可以访问对应的对象,并且此进程进入等待池中,用户可以用notify等方法来唤醒该线程。

public class ThreadDemo2 {

	public static void main(String[] args) {
		Object object=new Object();
		System.out.println("主线程开始");
		new Thread(new Runnable(){
			@Override
			public void run() {
				synchronized (object) {
					try {
						Thread.sleep(2000);
						object.notify();
						System.out.println("唤醒主线程");
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}).start();
		try{
			synchronized (object) {
				System.out.println("主线程等待中");
				object.wait();
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("主线程停止");
	}
}

以上示例中,由于在子线程启动之后,主线程调用了objectwait()方法,使得主线程进入等待状态,等到子线程中执行objcet.notify()方法之后,主线程才会被唤醒,执行结果如下:

主线程开始
主线程等待中
唤醒主线程
主线程停止

sleep():当一个线程执行此方法时,进入睡眠状态,但不释放对象锁。这个方法理解比较简单,此处不做示例。

join():当一个线程执行此方法是,其他线程在执行在当前线程完之前不执行。

public class ThreadDemo3 {

	public static void main(String[] args) {
		MyThread t1=new MyThread();
		MyThread t2=new MyThread();
		t1.start();
		try {
			System.out.println("启动线程1");
			t1.join();
			t2.start();
			System.out.println("启动线程2");
			t2.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("主线程执行完毕");
	}
	
}
class MyThread extends Thread{
	
	@Override
	public void run(){
		try {
			Thread.sleep(2000);
			System.out.println(Thread.currentThread().getName()+"正在运行");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

以上示例,由于t1启动之后,立刻调用了join方法,故其他线程会等待其执行完毕之后,再继续执行,同理,t2执行值后调用join方法,故主线程等待到t2执行完毕之后才继续执行。输出结果如下:

启动线程1
Thread-0正在运行
启动线程2
Thread-1正在运行
主线程执行完毕

yield():线程礼让,当前线程释放对象锁,并且让出执行权限,转换为就绪状态。


public class ThreadDemo4 {
	
	public static void main(String[] args) {
		Thread t1=new MyThread(true);
		Thread t2=new MyThread(false);
		t1.start();
		t2.start();
	}

}

class MyThread extends Thread{
	
	private boolean isYield;  //是否进行线程礼让
	
	public MyThread(boolean yield){
		isYield=yield;
	}
	
	@Override
	public void run(){
		for(int i=0;i<6;i++){
			if(i==3&&isYield){
				System.out.println(Thread.currentThread().getName()+"线程礼让");
				Thread.yield();
			}
			System.out.println(Thread.currentThread().getName()+"\ti="+i);
		}
	}
}

输出结果如下:

Thread-1	i=0
Thread-0	i=0
Thread-1	i=1
Thread-0	i=1
Thread-1	i=2
Thread-0	i=2
Thread-1	i=3
Thread-0线程礼让
Thread-1	i=4
Thread-1	i=5
Thread-0	i=3
Thread-0	i=4
Thread-0	i=5

由于我们控制当i等于3的时候t1Thread-0执行yield函数,故在上面输出的结果输出“Thread-0线程礼让”之后,并没有立刻输出“Thread-0 i=3”而是让出执行权限,进入就绪状态,t2继续执行,所以输出“Thread-1 i=4”。可以看出yield就是让出当前线程的执行权,让其他线程优先执行。





你可能感兴趣的:(java)