基础知识《四》---Java多线程学习总结

一、线程的基本概念
简单的说:线程就是一个程序里不同的执行路径,在同一个时间点上cpu只会有一个线程在执行,Java里的多线程是通过java.lang.Thread类来实现的,每个线程都拥有自己独立的方法栈空间。

二、java线程的创建和启动
第一种
定义线程类实现Runnable接口:
Thread myThread = new Thread(target) //target为Runnable接口类型
Runnable中只有一个方法:
public void run();用以定义线程运行体
第二种
可以定义一个Thread的子类并重写其run方法:
clas MyThread extends Thread{
public void run(){}
}
线程类必须通过执行Thread的start()方法启动一个新的线程,如果调用run()方法是属于方法的调用,不会启动一个新的线程,推荐使用第一种方式创建线程,使用接口较为灵活。

三、线程状态装换
调用线程start()方法时,线程进入就绪状态,Cpu分配时间片,线程进入运行状态,时间片结束,run()方法未执行完,线程进入阻塞状态。

四、线程控制基本方法
 isAlive() //判断线程是否还“活着”,即线程是否还未终止
getPriority() //获得线程的优先级数值
setPriority() //设置线程的优先级指数
Thread.sleep() //静态方法,将当前线程睡眠指定毫秒数
join()  //调用某线程的该方法,将当前线程与该线程合并,
//即等待该线程结束,再回复当前线程的运行。
yield()  //让出CPU,当前线程进入就绪状态等待调度
interrupt() //中断线程
wait()  //当前线程进入对象的wait pool
notify()/notifyAll //唤醒对象的wait pool中的一个/所有等待线程

五、sleep方法
Thread的静态方法
public static void sleep(long millis)throws InterruptedException
必须对异常进行捕捉
Thread.currentThread();  //拿到当前线程

六、interrupt方法一种让线程退出的方式。

 1 import java.util.*;  
 2 public class TestInterrupt{  
 3     public static void main(String[] args){  
 4         MyThread t = new MyThread();  
 5         t.start();  
 6         try{Thread.sleep(10000);}  
 7         catch(InterruptedException i){}  
 8         t.interrupt();  
 9     }  
10 }  
11  
12 class MyThread extends Thread{  
13     public void run(){  
14         while(true){  
15             try{  
16                 System.out.println("------"+new Date()+"-----");  
17                 Thread.sleep(1000);  
18             }catch(InterruptedException i){  
19                 return;  
20             }  
21         }  
22     }  
23 }  
24  

七、join和yield方法 
t.join(); //t的run()方法完才会继续执行当前线程方法体
//也就是两个线程变成了一个线程

join方法的功能就是使异步执行的线程变成同步执行。也就是说,当调用线程实例的start方法后,这个方法会立即返回,如果在调用start方法后后需要使用一个由这个线程计算得到的值,就必须使用join方法。如果不使用join方法,就不能保证当执行到start方法后面的某条语句时,这个线程一定会执行完。

下面的代码演示了join的用法。

 1 package mythread;  
 2  
 3 public class JoinThread extends Thread  
 4 {  
 5     public static int n = 0;  
 6  
 7     static synchronized void inc()  
 8     {  
 9         n++;  
10     }  
11     public void run()  
12     {  
13         for (int i = 0; i < 10; i++)  
14             try 
15             {  
16                 inc();  
17                 sleep(3);  // 为了使运行结果更随机,延迟3毫秒  
18                   
19             }  
20             catch (Exception e)  
21             {  
22             }                                        
23     }  
24     public static void main(String[] args) throws Exception  
25     {  
26      
27         Thread threads[] = new Thread[100];  
28         for (int i = 0; i < threads.length; i++)  // 建立100个线程  
29             threads[i] = new JoinThread();  
30         for (int i = 0; i < threads.length; i++)   // 运行刚才建立的100个线程  
31             threads[i].start();  
32         if (args.length > 0)    
33             for (int i = 0; i < threads.length; i++)   // 100个线程都执行完后继续  
34                 threads[i].join();  
35         System.out.println("n=" + JoinThread.n);  
36     }  
37 }  

 

在例程2-8中建立了100个线程,每个线程使静态变量n增加10。如果在这100个线程都执行完后输出n,这个n值应该是1000。

1.  测试1

使用如下的命令运行上面程序:

  1. java mythread.JoinThread 

程序的运行结果如下:

n=442

这个运行结果可能在不同的运行环境下有一些差异,但一般n不会等于1000。从上面的结果可以肯定,这100个线程并未都执行完就将n输出了。

2.  测试2

使用如下的命令运行上面的代码:

在上面的命令行中有一个参数join,其实在命令行中可以使用任何参数,只要有一个参数就可以,这里使用join,只是为了表明要使用join方法使这100个线程同步执行。

程序的运行结果如下:

n=1000

无论在什么样的运行环境下运行上面的命令,都会得到相同的结果:n=1000。这充分说明了这100个线程肯定是都执行完了,因此,n一定会等于1000。


t.yield(); //暂停当前正在执行的线程对象,并执行其他线程。方法为静态
//哪个线程体执行此方法,哪个线程让步

 1 public class TestYield {  
 2   public static void main(String[] args) {  
 3     MyThread3 t1 = new MyThread3("t1");  
 4     MyThread3 t2 = new MyThread3("t2");  
 5     t1.start(); t2.start();  
 6   }  
 7 }  
 8 class MyThread3 extends Thread {  
 9   MyThread3(String s){super(s);}  
10   public void run(){  
11     for(int i =1;i<=100;i++){  
12       System.out.println(getName()+": "+i);  
13       if(i%10==0){  
14         yield();  
15       }  
16     }  
17   }  
18 } 

八、线程优先级别 
线程的优先级用数字表示,范围从1到10,一个线程的缺省优先级为5.
Thread.MAX_PRIORITY=1
Thread.MIN_PRIORITY=10
Thread.NORM_PRIORITY=5
例:t.setPriority(Thread.NORM_PRIORITY+3);
九、线程同步
1.同步代码块
synchronized(this){  //在执行代码块过程中,不会被其他线程打断
...  
}
public sunchronized void method //执行此方法时,当前对象被锁定
在Java语言中,引入了对象互斥锁的概念,保证共享数据操作的完整性,每个对象 都对应一个可称为"互斥锁"的标记,这个标记保证在任一时刻,只能有一个线程访 问该对象。
2.线程死锁

 1 public class TestDeadLock implements Runnable {  
 2     public int flag = 1;  
 3     static Object o1 = new Object(), o2 = new Object();  
 4     public void run() {  
 5 System.out.println("flag=" + flag);  
 6         if(flag == 1) {  
 7             synchronized(o1) {  
 8                 try {  
 9                     Thread.sleep(500);  
10                 } catch (Exception e) {  
11                     e.printStackTrace();  
12                 }  
13                 synchronized(o2) {  
14                     System.out.println("1");      
15                 }  
16             }  
17         }  
18         if(flag == 0) {  
19             synchronized(o2) {  
20                 try {  
21                     Thread.sleep(500);  
22                 } catch (Exception e) {  
23                     e.printStackTrace();  
24                 }  
25                 synchronized(o1) {  
26                     System.out.println("0");  
27                 }  
28             }  
29         }  
30     }      
31       
32     public static void main(String[] args) {  
33         TestDeadLock td1 = new TestDeadLock();  
34         TestDeadLock td2 = new TestDeadLock();  
35         td1.flag = 1;  
36         td2.flag = 0;  
37         Thread t1 = new Thread(td1);  
38         Thread t2 = new Thread(td2);  
39         t1.start();  
40         t2.start();  
41           
42     }  
43 } 

 

十、生产者消费者问题

 1 public class ProducerConsumer {  
 2     public static void main(String[] args) {  
 3         SyncStack ss = new SyncStack();  
 4         Producer p = new Producer(ss);  
 5         Consumer c = new Consumer(ss);  
 6         new Thread(p).start();  
 7         new Thread(p).start();  
 8         new Thread(p).start();  
 9         new Thread(c).start();  
10     }  
11 }  
12  
13 class WoTou {  
14     int id;   
15     WoTou(int id) {  
16         this.id = id;  
17     }  
18     public String toString() {  
19         return "WoTou : " + id;  
20     }  
21 }  
22  
23 class SyncStack {        //栈实现  
24     int index = 0;  
25     WoTou[] arrWT = new WoTou[6];    //相当于装物品的篮子  
26       
27     public synchronized void push(WoTou wt) {    //生产物品,线程安全  
28         while(index == arrWT.length) {        //当篮子满了线程等待  
29             try {              
30                 this.wait();          
31             } catch (InterruptedException e) {  
32                 e.printStackTrace();  
33             }  
34               
35         }  
36         this.notifyAll();    //开始生产时,叫醒等待的其他线程开始消费  
37         arrWT[index] = wt;      
38         index ++;  
39     }  
40       
41     public synchronized WoTou pop() {        //消费物品,线程安全  
42         while(index == 0) {            //如果篮子空了  
43             try {  
44                 this.wait();        //线程等待,等待生产者开始                           
45 //生产,叫醒此线程  
46             } catch (InterruptedException e) {  
47                 e.printStackTrace();  
48             }  
49               
50         }  
51         this.notifyAll();            //消费时喊醒生产者生产  
52         index--;  
53         return arrWT[index];  
54     }  
55 }  
56  
57 class Producer implements Runnable {            //生产者类  
58     SyncStack ss = null;  
59     Producer(SyncStack ss) {  
60         this.ss = ss;  
61     }  
62       
63     public void run() {  
64         for(int i=0; i<20; i++) {    //生产20个  
65             WoTou wt = new WoTou(i);  
66             ss.push(wt);              
67             System.out.println("生产了:" + wt);  
68             try {  
69                 Thread.sleep((int)(Math.random() * 200));  
70             } catch (InterruptedException e) {  
71                 e.printStackTrace();  
72             }              
73         }  
74     }  
75 }  
76  
77 class Consumer implements Runnable {  
78     SyncStack ss = null;  
79     Consumer(SyncStack ss) {  
80         this.ss = ss;  
81     }  
82       
83     public void run() {  
84         for(int i=0; i<20; i++) {        //消费20个  
85             WoTou wt = ss.pop();  
86             System.out.println("消费了: " + wt);  
87             try {  
88                 Thread.sleep((int)(Math.random() * 1000));  
89             } catch (InterruptedException e) {  
90                 e.printStackTrace();  
91             }              
92         }  
93     }  
94 }  

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。