参考
http://www.runoob.com/java/java-multithreading.html
http://www.infoq.com/cn/articles/cf-java-thread
https://www.ibm.com/developerworks/cn/java/multithreading/#ibm-pcon(其实看这个就够了)
线程基本概念
- 进程(process):有一个包含了程序内容和数据的地址空间,以及其它的资源,包括打开的文件、子进程和信号处理器等。不同进程的地址空间是互相隔离的。
- 线程(thread):表示的是程序的执行流程,是CPU调度的基本单位。线程有自己的程序计数器、寄存器、栈和帧等。引入线程的动机在于操作系统中阻塞式I/O的存在。当一个线程所执行的I/O被阻塞的时候,同一进程中的其它线程可以使用CPU来进行计算。这样的话,就提高了应用的执行效率。线程的概念在主流的操作系统和编程语言中都得到了支持。
- 多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销
- 包含关系: 一个进程(process)包括由操作系统分配的内存空间,包含一个或多个线程(thread)。
- 目的:多线程能满足程序员编写高效率的程序来达到充分利用CPU的目的
- 生命周期:新建-就绪-运行-(阻塞)-死亡
- **线程优先级:**Java线程的优先级是一个整数,其取值范围是1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )
- 可见性:可见性(visibility)的问题是Java多线程应用中的错误的根源。
- 锁 同步 中断线程
- > 详见 http://www.infoq.com/cn/articles/cf-java-thread
通过实现Runnable接口来创建线程
package Thread;
/**
* Created by zhangzexiang on 2016/9/9.
*
* 创建一个线程方法之一:通过实现Runnable接口来创建线程
*
* 重写 public void run()
* 理解run()可以调用其他方法,使用其他类,并声明变量,就像主线程一样
*
* 在类中先实例化一个线程对象
* 常用: Thread(Runnable threadOb, String threadName);
* threadOb :是一个实现Runnable接口的类的实例
* threadName :指定线程的名字
*
*
* 新线程创建之后,你调用它的start()方法它才会运行。
*
*
*/
public class NewThread{
public static void main(String args[]){
new NewThread1(); //create new thread
try{
for(int i=5; i>0; i--){
System.out.println("Main Thread "+i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main thread exiting");
}
}
//创建一个新的线程
class NewThread1 implements Runnable {
Thread t;
NewThread1(){
//创建第二个新线程
t = new Thread(this,"Demo Thread");
System.out.println("child thread: " + t);
t.start(); //begin thread
}
//the second thread entrance(入口)
@Override
public void run() {
try{
for(int i=5; i>0; i--){
System.out.println("chaild thread:" + i);
//pause thread
Thread.sleep(50);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Exiting child thread");
}
}
运行结果
child thread: Thread[Demo Thread,5,main]
Main Thread 5
chaild thread:5
chaild thread:4
Main Thread 4
chaild thread:3
chaild thread:2
Main Thread 3
chaild thread:1
Exiting child thread
Main Thread 2
Main Thread 1
main thread exiting
主方法算是第一个线程,且不用start() 不用run()就可以运行(自己猜的)
第二个线程先用构造函数创建,然后用其方法运行
通过继承Thread来创建线程
package Thread;
/**
* Created by zhangzexiang on 2016/9/9.
*
* 通过继承Thread来创建线程
*
*
* 创建一个线程的第二种方法是创建一个新的类,该类继承Thread类,然后创 建一个该类的实例。
* 继承类必须重写run()方法,该方法是新线程的入口点。它也必须调用*start()方法才能执行。
*/
public class ExtendThread {
public static void main(String args[]) {
new NewThread2(); // 创建一个新线程
try {
for(int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
class NewThread2 extends Thread {
NewThread2() {
// 创建第二个新线程
super("Demo Thread");
System.out.println("Child thread: " + this);
start(); // 开始线程
}
// 第二个线程入口
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
// 让线程休眠一会
Thread.sleep(50);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
运行结果
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Child Thread: 1
Main Thread: 3
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
俩种实现方法比较
http://blog.csdn.net/ns_code/article/details/17161237
这篇博客评论中有歧义,我也不是很明白谁对谁错,总之网上的东西不一定都对,博客也是
Java中实现多线程有两种方法:继承Thread类、实现Runnable接口,在程序开发中只要是多线程,肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下优势:
1、可以避免由于Java的单继承特性而带来的局限;
2、增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的;
3、适合多个相同程序代码的线程区处理同一资源的情况。
package Thread;
/**
* Created by zhangzexiang on 2016/9/9.
*
* 火车票出售实例
*/
public class TestTicket {
public static void main(String[] args)
{
Resource rs = new Resource(20);
//new几个Thread相当于有几个售票窗口
//如下可以用4个窗口同时售卖
new Thread(new Seller(1,rs)).start();
new Thread(new Seller(2,rs)).start();
new Thread(new Seller(3,rs)).start();
new Thread(new Seller(4,rs)).start();
}
static class Resource
{
int ticketNum = 50;
boolean flag = false ; // 定义票是否卖完
public Resource(){}
public Resource(int num)
{
this.ticketNum = num;
}
//这里保证售卖的票不是同一张票 ---》 synchronized
public synchronized void sellTicket(Seller s)
{
if (ticketNum > 0)
{
System.out.println("第" + s.num + "售票点卖出了第" + ticketNum + "张票……");
ticketNum--;
}
else
{
flag = true;
}
}
}
/**
* 售票点类
*
*/
static class Seller implements Runnable
{
int num;
Resource rs;
public Seller(int num,Resource rs)
{
this.num = num;
this.rs = rs;
}
public final void run()
{
while (!rs.flag)
{
/**
* 调用资源类的同步方法
*/
rs.sellTicket(this);
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
程序运行结果(1秒刷4行)
第1售票点卖出了第20张票……
第3售票点卖出了第19张票……
第2售票点卖出了第18张票……
第4售票点卖出了第17张票……
第1售票点卖出了第16张票……
第3售票点卖出了第15张票……
第4售票点卖出了第14张票……
第2售票点卖出了第13张票……
第2售票点卖出了第12张票……
第1售票点卖出了第11张票……
第4售票点卖出了第10张票……
第3售票点卖出了第9张票……
第4售票点卖出了第8张票……
第1售票点卖出了第7张票……
第2售票点卖出了第6张票……
第3售票点卖出了第5张票……
第1售票点卖出了第4张票……
第3售票点卖出了第3张票……
第2售票点卖出了第2张票……
第4售票点卖出了第1张票……
Process finished with exit code 0