java-线程

线程是一个程序里面不同的执行路径(理解这个就可以了)

1.线程的基本概念
可以通过创建Thread的实例来创建新的线程。
每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。
通过调用Thread类的start()方法来启动一个线程。

 

2.线程的创建和启动
第一种
定义线程类实现Runnable接口
Thread myThread = new Thread(target) //target为Runnable接口类型。
Runnable中只有一个方法:
public void run();//用以定义线程运行体。
使用Runnable接口可以为多个线程提供共享的数据。
在实现Runnable接口的类的run方法定义中可以使用Thread的静态方法:
public static Thread currentThread() //获取当前线程的引用。

第二种
可以定义一个Thread的子类并重写其run方法:
class MyThread extends Thread{
public void run(){...}
}
然后生成该类的对象:
MyThread myThread = new MyThread(...)

例子1:使用Runnable接口实现

 1 //main主线程和子线程并行执行
 2 public class TestThread1 {
 3     public static void main(String[] args) {
 4         Runnable1 r = new Runnable1();
 5         //r.run();//方法调用
 6         Thread thread = new Thread(r);
 7         thread.start();//启动一个新线程
 8         for(int i=0;i<100;i++){
 9             System.err.println("MainThread-----"+i);
10         }
11     }
12 }
13 
14 class Runnable1 implements Runnable {
15     public void run() {
16         for(int i=0;i<100;i++){
17             System.out.println("Runner1:"+i);
18         }
19     }
20 }

 例子2:从Thread类继承

 1 //main主线程和子线程并行执行
 2 public class TestThread1 {
 3     public static void main(String[] args) {
 4         Runnable1 thread = new Runnable1();
 5         thread.start();//启动一个新线程
 6         for(int i=0;i<100;i++){
 7             System.err.println("MainThread-----"+i);
 8         }
 9     }
10 }
11 
12 class Runnable1 extends Thread{
13     public void run() {
14         for(int i=0;i<100;i++){
15             System.out.println("Runner1:"+i);
16         }
17     }
18 }

 

3.常用方法

sleep方法
可以调用Thread的静态方法:
public static void sleep(long milis) throws InterruptedExecption使得当前线程休眠(暂时停止执行millis毫秒)。
由于是静态方法,sleep可以由类名之间调用:
Thread.sleep(...)

例子3

 1 public class TestInterrupt {
 2     public static void main(String[] args) {
 3         MyThread thread = new MyThread();
 4         thread.start();
 5         try {
 6             Thread.sleep(10000);//在哪个线程里调用Thread.sleep方法就让哪个线程睡眠
 7         } catch (InterruptedException e) {}
 8         thread.interrupt();//子线程结束(不是让子线程结束的最好的方法,比较粗暴,可能会导致打开的资源来不及关)
 9         //thread.stop();//(已废弃)方式比interrupt更粗暴。
10     }
11 }
12 
13 class MyThread extends Thread{
14     @Override
15     public void run() {//不可以在后面写throws exception,原因是run重写的,重写的方法不能抛出比被重写方法不同的异常
16         while(true){
17             System.err.println("===="+new Date()+"====");
18             try {
19                 sleep(1000);
20             } catch (InterruptedException e) {
21                 return;
22             }
23         }
24     }
25 }

例子4:使用一个变量控制子程序结束

 1 public class TestInterrupt {
 2     public static void main(String[] args) {
 3         MyThread thread = new MyThread();
 4         thread.start();
 5         try {
 6             Thread.sleep(10000);
 7         } catch (InterruptedException e) {}
 8         thread.flag = false;
 9     }
10 }
11 
12 class MyThread extends Thread{
13     boolean flag = true;//定义一个变量来控制
14     public void run() {
15         while(flag){
16             System.err.println("===="+new Date()+"====");
17             try {
18                 sleep(1000);
19             } catch (InterruptedException e) {
20                 return;
21             }
22         }
23     }
24 }

 

join方法

合并某个线程

例子5

 1 public class TestJoin {
 2     public static void main(String[] args) {
 3         MyThread2 t1 = new MyThread2("t1");
 4         t1.start();
 5         try {
 6             t1.join();//合并t1,把t1合并到主线程来,等t1执行完才执行主线程的
 7         } catch (Exception e) {}
 8         for(int i=0;i<10;i++){
 9             System.err.println("main Thread is "+i);
10         }
11     }
12 }
13 
14 class MyThread2 extends Thread{
15     public MyThread2(String s) {
16         super(s);
17     }
18     @Override
19     public void run() {
20         for(int i=0;i<10;i++){
21             System.err.println("i am "+getName());
22             try {
23                 sleep(1000);
24             } catch (Exception e) {
25                 return;
26             }
27         }
28     }
29 }

 

yield方法(用的不多)

让出CPU,给其他线程执行的机会

例子6

 1 public class TestYeild {
 2     public static void main(String[] args) {
 3         MyThread3 thread3 = new MyThread3("t3");
 4         MyThread3 thread1 = new MyThread3("t1");
 5         thread3.start();
 6         thread1.start();
 7     }
 8 }
 9 
10 class MyThread3 extends Thread{
11     public MyThread3(String s) {
12         super(s);
13     }
14     @Override
15     public void run() {
16         for(int i=0;i<50;i++){
17             System.err.println(getName()+"-----"+ i);
18             if (i%10==0) {
19                 yield();
20             }
21         }
22     }
23 }

 

线程的优先级别

用数字表示,范围从1到10,默认是5,优先级越高的得到的CPU的执行的时间片就会越多。

例子6

 1 public class TestPriority {
 2     public static void main(String[] args) {
 3         Thread thread1 = new Thread(new t1());
 4         Thread thread2 = new Thread(new t2());
 5         thread1.setPriority(Thread.NORM_PRIORITY+3);
 6         thread1.start();
 7         thread2.start();
 8     }
 9 }
10 
11 class t1 implements Runnable {
12     public void run() {
13         for(int i=0;i<10;i++){
14             System.err.println("t1:"+i);
15         }
16     }
17 }
18 
19 class t2 implements Runnable {
20     public void run() {
21         for(int i=0;i<10;i++){
22             System.err.println("--------t2:"+i);
23         }
24     }
25 }

执行结果

t1:0
t1:1
--------t2:0
t1:2
t1:3
t1:4
t1:5
t1:6
t1:7
t1:8
t1:9
--------t2:1
--------t2:2
--------t2:3
--------t2:4
--------t2:5
--------t2:6
--------t2:7
--------t2:8
--------t2:9
结果

 

4.线程同步

例子7:不使用线程同步会出现以下问题(结果不对)

 1 public class TestSync implements Runnable {
 2     Timer timer = new Timer();
 3     public static void main(String[] args) {
 4         TestSync test = new TestSync();
 5         Thread t1 = new Thread(test);
 6         Thread t2 = new Thread(test);
 7         t1.setName("t1");
 8         t2.setName("t2");
 9         t1.start();
10         t2.start();
11     }
12     public void run() {
13         timer.add(Thread.currentThread().getName());
14     }
15 }
16 
17 class Timer{
18     private static int num =0;
19     public void add(String name) {
20         num++;
21         try {
22             Thread.sleep(1);
23         } catch (InterruptedException e) {}
24             System.err.println(name +"你是第"+num+"个使用timer的线程");
25         
26     }
27 }

结果

t2你是第2个使用timer的线程
t1你是第2个使用timer的线程
结果

例子8:

 1 public class TestSync implements Runnable {
 2     Timer timer = new Timer();
 3     public static void main(String[] args) {
 4         TestSync test = new TestSync();
 5         Thread t1 = new Thread(test);
 6         Thread t2 = new Thread(test);
 7         t1.setName("t1");
 8         t2.setName("t2");
 9         t1.start();
10         t2.start();
11     }
12     public void run() {
13         timer.add(Thread.currentThread().getName());
14     }
15 }
16 
17 class Timer{
18     private static int num =0;
19     public void add(String name) {
20     //    public synchronized void add(String name) { //也可以写成这样
21         synchronized (this) {//该方法被执行过程中当前对象被锁定
22         num++;
23         try {
24             Thread.sleep(1);
25         } catch (InterruptedException e) {}
26             System.err.println(name +"你是第"+num+"个使用timer的线程");
27         }
28     }
29 }

结果

t1你是第1个使用timer的线程
t2你是第2个使用timer的线程
结果

 

5.多线程会造成的问题

死锁

例子9

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

 6.生产者消费者问题

 例子10

 1 /*
 2  * 生产者消费者问题
 3  * 要  点:
 4  *        1. 共享数据的不一致性/临界资源的保护
 5  *        2. Java对象锁的概念
 6  *        3. synchronized关键字/wait()及notify()方法
 7  */
 8 public class ProducerConsumer {
 9     public static void main(String[] args) {
10         SyncStack stack = new SyncStack();
11         Runnable p = new Producer(stack);
12         Runnable c = new Customer(stack);
13         Thread p1 =new Thread(p);
14         Thread c1 = new Thread(c);
15         p1.start();
16         c1.start();
17     }
18 }
19 
20 class SyncStack{ //支持多线程同步操作的堆栈的实现
21     private int index =0;
22     private char[] data = new char[6];
23     public synchronized void push(char c) {
24         if(index == data.length){
25             try {
26                 this.wait();
27             } catch (InterruptedException e) {
28             }
29         }
30         this.notify();
31         data[index] = c;
32         index++;
33     }
34     public synchronized char pop() {
35         if(index == 0){
36             try {
37                 this.wait();
38             } catch (InterruptedException e) {
39             }
40         }
41         this.notify();
42         index--;
43         return data[index];
44     }
45 }
46 
47 class Producer implements Runnable{
48     SyncStack stack;
49     public Producer(SyncStack s) {
50         stack =s;
51     }
52     
53     @Override
54     public void run() {
55         for(int i=0;i<20;i++){
56              char c =(char)(Math.random()*26+'A');
57              stack.push(c);
58              System.err.println("producer"+c);
59              try {
60                 Thread.sleep((int)Math.random()*1000);
61             } catch (InterruptedException e) {}
62         }
63         
64     }
65     
66 }
67 
68 class Customer implements Runnable{
69     SyncStack stack;
70     public Customer(SyncStack s) {
71         stack =s;
72     }
73     
74     @Override
75     public void run() {
76         for(int i=0;i<20;i++){
77              char c =stack.pop();
78              System.out.println("消费:"+c);
79              try {
80                 Thread.sleep((int)Math.random()*1000);
81             } catch (InterruptedException e) {}
82         }
83         
84     }
85 }

 

posted @ 2018-07-31 09:51  1315667459  阅读(175)  评论(0编辑  收藏  举报