Java 并发 (多线程) 讲解


多线程的概念是相对于顺序编程 而言的,在顺序编程里,程序只能按照一条线进行执行,而多线程可以打破这一限制,实现并发 效果。


多线程的基本实现方式


继承Thread


通过继承Thread类可以实现新的线程,这样会很简便,但一般来说,是不被建议这样使用的。

它最大的缺陷是,一旦继承了Thread类就无法继承别的类,对设计造成一定的影响。


以下的demo中,我们通过继承Thread类来实现多线程。

共开启5个线程,线程名字分别初始化为15的数字。每个线程开始执行后,均是每隔一秒输出一次当前状态。


class InheritThread extends Thread {
	
	private int waitSeconds = 5;
	
	private static int threadCount = 0;
	
	public InheritThread() {
		super(Integer.toString(threadCount++));
	}
	
	public void run() {
		while (waitSeconds > 0) {
			System.out.print(this);
			
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			waitSeconds--;
		}
	}
	
	//override toString method
	public String toString() {
		String name = getName();
		String info = "InheritThread:" +  name + ", current waitSeconds = " + waitSeconds + "\n";
		return info;
	}
}


public class TestClass {

	public static void main(String[] args) {

			Thread thread;
			for (int i = 0; i < 5; i++) {
				thread = new InheritThread();
				thread.start();
			}
	}

}

输出结果:(对于多线程问题,不同机器和平台上,同样的代码也可能产生不同的结果)

InheritThread:1, current waitSeconds = 5
InheritThread:2, current waitSeconds = 5
InheritThread:3, current waitSeconds = 5
InheritThread:4, current waitSeconds = 5
InheritThread:5, current waitSeconds = 5
InheritThread:1, current waitSeconds = 4
InheritThread:2, current waitSeconds = 4
InheritThread:3, current waitSeconds = 4
InheritThread:4, current waitSeconds = 4
InheritThread:5, current waitSeconds = 4
InheritThread:1, current waitSeconds = 3
InheritThread:2, current waitSeconds = 3
InheritThread:3, current waitSeconds = 3
InheritThread:4, current waitSeconds = 3
InheritThread:5, current waitSeconds = 3
InheritThread:1, current waitSeconds = 2
InheritThread:3, current waitSeconds = 2
InheritThread:2, current waitSeconds = 2
InheritThread:4, current waitSeconds = 2
InheritThread:5, current waitSeconds = 2
InheritThread:1, current waitSeconds = 1
InheritThread:2, current waitSeconds = 1
InheritThread:3, current waitSeconds = 1
InheritThread:4, current waitSeconds = 1
InheritThread:5, current waitSeconds = 1


实现Runnable接口


Runnable是JDK里的一个接口,我们可以把它理解为一个 "任务“, 即是我们要用它实现的线程执行的任务。

Thread类本身就是实现了Runnable接口的,所以我们才可以直接继承Thread类实现线程。


同样,我们只需实现Runnable接口(复写它的 run 方法), 就可以用它来实现线程。


以下的例子所做的操作和上个例子基本是一样的:

class ImpRunnable implements Runnable {

	private int waitSeconds = 5;
	
	private static int threadCount = 0;
	
	private final int myThreadCount = threadCount;
	
	public ImpRunnable() {
		threadCount++;
	}
	
	public void run() {
		while (waitSeconds > 0) {
			System.out.print(this);
			
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			waitSeconds--;
		}
	}
	
	//override toString method
	public String toString() {
		String name = "ImplRunnabeThread:" + myThreadCount;
		String info = name + ", current waitSeconds = " + waitSeconds + "\n";
		return info;
	}
	
}

public class TestClass {

	public static void main(String[] args) {

			Thread thread;
			for (int i = 0; i < 5; i++) {
				
				thread = new Thread(new ImpRunnable());
				thread.start();
			}
	}

}

输出结果:

ImplRunnabeThread:0, current waitSeconds = 5
ImplRunnabeThread:1, current waitSeconds = 5
ImplRunnabeThread:2, current waitSeconds = 5
ImplRunnabeThread:3, current waitSeconds = 5
ImplRunnabeThread:4, current waitSeconds = 5
ImplRunnabeThread:0, current waitSeconds = 4
ImplRunnabeThread:1, current waitSeconds = 4
ImplRunnabeThread:2, current waitSeconds = 4
ImplRunnabeThread:3, current waitSeconds = 4
ImplRunnabeThread:4, current waitSeconds = 4
ImplRunnabeThread:0, current waitSeconds = 3
ImplRunnabeThread:1, current waitSeconds = 3
ImplRunnabeThread:2, current waitSeconds = 3
ImplRunnabeThread:3, current waitSeconds = 3
ImplRunnabeThread:4, current waitSeconds = 3
ImplRunnabeThread:0, current waitSeconds = 2
ImplRunnabeThread:1, current waitSeconds = 2
ImplRunnabeThread:2, current waitSeconds = 2
ImplRunnabeThread:3, current waitSeconds = 2
ImplRunnabeThread:4, current waitSeconds = 2
ImplRunnabeThread:0, current waitSeconds = 1
ImplRunnabeThread:1, current waitSeconds = 1
ImplRunnabeThread:2, current waitSeconds = 1
ImplRunnabeThread:3, current waitSeconds = 1
ImplRunnabeThread:4, current waitSeconds = 1


几种常用的线程操作


休眠


可以通过  Thread.sleep( millseconds )方法使线程终止执行给定的时间。

(以上两个demo中均使用了该方法)


注意使用该方法时需要捕获 InterruptedException.


让步


系统在实现多线程时,其实是对cpu的使用时间进行了切分,通过策略分别分配给各个线程cpu的使用机会。


如果我们在实现线程时,某些时间段不需要使用cpu,那么我们可以通过 Thread.yield() 方法通知线程调度器: 我现在暂时不需要cpu了,让别的线程使用吧。


但是要注意:这仅仅是一个暗示或者提示,没有任何机制能够保证系统会分配给其他线程cpu使用。所以不要完全依赖于 yield 来调度多线程的执行。



设置优先级


初始化一个线程后,它会按照默认的优先级运行。但我们也可以认为设置线程的优先级。

cpu调度器会倾向于让优先级高的线程先执行,但并不是说低优先级的线程不被执行,只是执行的频率会相对低一些。

可以通过 getPriority()方法获取当前线程的优先级,通过setPriority()方法设置优先级。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章