JAVA基础--线程
sleep和wait的区别:
1. sleep是Thread的方法, wait是object的方法
2. sleep占着CPU睡觉, wait等待CPU,不占用CPU
线程是一个程序内部的顺序控制流
线程和进程的区别:
1. 每个进程都有独立的代码和数据空间, 进程间的切换会有很大的开销.
2. 线程可以看成是轻量级的进程, 同一类线程共享代码和数据空间, 每个线程有独立的运行栈和程序计数器PC, 线程切换的开销小.
3. 多进行, 在操作系统中能同时运行多个任务(程序)
4. 多线程:在同一个程序可以有多个顺序刘同时执行.
通过创建Thread的实例来创建新的线程
每个线程都通过特定Thread对象对应的run方法来完成操作, 方法run称为线程体
通过调用Thread类的start方法启动一个线程
run是方法调用,start是开启一个线程
以下程序只有一个线程 main, 主线程
public class { public static void main(String[] args) { m1(); } public static void m1() { m2(); m3(); } public static void m2() {} public static void m3() {} }
进程: 一个class文件, 一个exe文件, 是个静态的概念.进程的执行指的是一个主线程开始执行, 即main开始.
所以机器里我们运行的都是线程.
建议使用以下接口的方式:
public class TestThread1 { public static void main(String args[]) { Runner1 r = new Runner1(); Thread t = new Thread(r); t.start(); for(int i=0; i<100; i++) { System.out.println("Main Thread:------" + i); } } } class Runner1 implements Runnable { public void run() { for(int i=0; i<100; i++) { System.out.println("Runner1 :" + i); } } }
还有一种方法,继承Thread,不建议使用:
public class TestThread1 { public static void main(String args[]) { Runner1 r = new Runner1(); r.start(); for(int i=0; i<100; i++) { System.out.println("Main Thread:------" + i); } } } class Runner1 extends Thread { public void run() { for(int i=0; i<100; i++) { System.out.println("Runner1 :" + i); } } }
线程状态转换:
创建-->start-->就绪--> 运行-->终止 运行-->阻塞状态-->就绪
线程控制的方法:
isAlive(): 阻塞,运行, 就绪,
getPriority() 获得优先级
setPriority(): 设置优先级
Thread.sleep(): 将当前线程睡眠指定毫秒数
join(): 合并, 等改线程结束再恢复当前线程的运行
yield(): 让出CPU, 当前线程进去就绪状态等待调度
wait(): 当前线程进入wait pool
sleep方法: Thread类的静态方法:
import java.util.*; public class TestInterrupt { public static void main(String[] args) { Runner r = new Runner(); Thread t = new Thread(r); t.start(); try {Thread.sleep(10000);} catch (InterruptedException e) {} //t.interrupt(); //打断子线程,比较粗暴
r.flag=false; //替换上面的打断子线程的方式, 用这种方式, run方法里的return也可以注释掉了 } } class Runner implements Runnable { boolean flag = true; public void run(){ while(flag){ System.out.println("==="+new Date()+"==="); try { Thread.sleep(1000); } catch (InterruptedException e) { //被打算后进入异常, return return; } } } }
结果:每隔一秒显示一次:
===Fri Apr 08 10:53:44 CST 2016=== ===Fri Apr 08 10:53:45 CST 2016=== ===Fri Apr 08 10:53:46 CST 2016=== ===Fri Apr 08 10:53:47 CST 2016=== ===Fri Apr 08 10:53:48 CST 2016=== ===Fri Apr 08 10:53:49 CST 2016=== ===Fri Apr 08 10:53:50 CST 2016=== ===Fri Apr 08 10:53:51 CST 2016=== ===Fri Apr 08 10:53:52 CST 2016=== ===Fri Apr 08 10:53:53 CST 2016===
join用法:相当于调用, 如果main里调用join, 那么会等join的线程执行完才能执行自己的线程:
public class TestJoin { public static void main(String[] args) { MyThread2 t1 = new MyThread2("abcde"); t1.start(); try { t1.join(); } catch (InterruptedException e) {} for(int i=1;i<=10;i++){ System.out.println("i am main thread"); } } } class MyThread2 extends Thread { MyThread2(String s){ super(s); } public void run(){ for(int i =1;i<=10;i++){ System.out.println("i am "+getName()); try { sleep(1000); } catch (InterruptedException e) { return; } } } }
结果:
i am abcde i am abcde i am abcde i am abcde i am abcde i am abcde i am abcde i am abcde i am abcde i am abcde i am main thread i am main thread i am main thread i am main thread i am main thread i am main thread i am main thread i am main thread i am main thread i am main thread
yield方法: 让出CPU, 给其他线程执行的机会:
只要运行的线程 i 被10整除, 就让出给别的线程运行
public class TestYield { public static void main(String[] args) { MyThread3 t1 = new MyThread3("t1"); MyThread3 t2 = new MyThread3("t2"); t1.start(); t2.start(); } } class MyThread3 extends Thread { MyThread3(String s){super(s);} public void run(){ for(int i =1;i<=100;i++){ System.out.println(getName()+": "+i); if(i%10==0){ yield(); } } } }
线程的优先级:
public class TestPriority { public static void main(String[] args) { Thread t1 = new Thread(new T1()); Thread t2 = new Thread(new T2()); t1.setPriority(Thread.NORM_PRIORITY + 3); t1.start(); t2.start(); } } class T1 implements Runnable { public void run() { for(int i=0; i<100; i++) { System.out.println("T1: " + i); } } } class T2 implements Runnable { public void run() { for(int i=0; i<100; i++) { System.out.println("------T2: " + i); } } }
Thread.MIN_PRIORITY=1; Thread.MAX_PRIORITY=10; Thread.NORM_PRIORITY=5;
同一个线程对象可以定义两个Thread:
public class TestThread2 { public static void main(String args[]) { Runner2 r = new Runner2(); Thread t1 = new Thread(r); Thread t2 = new Thread(r); t1.start(); t2.start(); } } class Runner2 implements Runnable { public void run() { for(int i=0; i<30; i++) { System.out.println("No. " + i); } } }
被10整除就停顿2s:
public class TestThread3{ public static void main(String args[]) { Runner3 r = new Runner3(); Thread t = new Thread(r); t.start(); } } class Runner3 implements Runnable { public void run() { for(int i=0; i<30; i++) { if(i%10==0 && i!=0) { try{ Thread.sleep(2000); }catch(InterruptedException e){} } System.out.println("No. " + i); } } }
如何恰当的结束线程, 用flag:
public class TestThread4 { public static void main(String args[]){ Runner4 r = new Runner4(); Thread t = new Thread(r); t.start(); for(int i=0;i<100000;i++){ if(i%10000==0 & i>0) System.out.println("in thread main i=" + i); } System.out.println("Thread main is over"); r.shutDown(); //t.stop(); } } class Runner4 implements Runnable { private boolean flag=true; public void run() { int i = 0; while (flag==true) { System.out.print(" " + i++); } } public void shutDown() { flag = false; } }
isAlive:
public class TestThread6 { public static void main(String args[]){ Thread t = new Runner6(); t.start(); for(int i=0; i<50; i++) { System.out.println("MainThread: " + i); } } } class Runner6 extends Thread { public void run() { System.out.println(Thread.currentThread().isAlive()); for(int i=0;i<50;i++) { System.out.println("SubThread: " + i); } } }
线程同步: synchronized:
执行方法的过程中当前对象被锁定, 这样对象控制一个过程, 别的线程不可打扰.
public class TestSync implements Runnable { Timer timer = new Timer(); public static void main(String[] args) { TestSync test = new TestSync(); Thread t1 = new Thread(test); Thread t2 = new Thread(test); t1.setName("t1"); t2.setName("t2"); t1.start(); t2.start(); } public void run(){ timer.add(Thread.currentThread().getName()); } } class Timer{ private static int num = 0; public synchronized void add(String name){ //执行方法的过程中锁定当前对象 //synchronized (this) { //方法不加同步的话, 可以用此方法体的方式锁定 num ++; try {Thread.sleep(1);} catch (InterruptedException e) {} System.out.println(name+", 你是第"+num+"个使用timer的线程"); //} } }
结果:
不加synchronized的话, 就都显示2
t1, 你是第1个使用timer的线程 t2, 你是第2个使用timer的线程
用synchronize的时候会出现死锁的现象,比如线程A执行过程中,锁定某一个对象1. 另一个线程B锁定另一个对象2, 线程A 需要继续锁定对象2, 线程B需要锁定对象1, 就会发生死锁.
public class TestDeadLock implements Runnable { public int flag = 1; static Object o1 = new Object(), o2 = new Object(); public void run() { System.out.println("flag=" + flag); if(flag == 1) { synchronized(o1) { try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } synchronized(o2) { System.out.println("1"); } } } if(flag == 0) { synchronized(o2) { try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } synchronized(o1) { System.out.println("0"); } } } } public static void main(String[] args) { TestDeadLock td1 = new TestDeadLock(); TestDeadLock td2 = new TestDeadLock(); td1.flag = 1; td2.flag = 0; Thread t1 = new Thread(td1); Thread t2 = new Thread(td2); t1.start(); t2.start(); } }
结果: 线程不动了:
flag=1 flag=0
线程锁死后, 别的方法还可以访问
public class TT implements Runnable { int b = 100; public synchronized void m1() throws Exception{ b = 1000; Thread.sleep(5000); System.out.println("b = " + b); } public void m2() { System.out.println(b); } public void run() { try { m1(); } catch(Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { TT tt = new TT(); Thread t = new Thread(tt); t.start(); Thread.sleep(1000); tt.m2(); } }
结果:
1000 b = 1000
上例子改一下:
public class TT implements Runnable { int b = 100; public synchronized void m1() throws Exception{ b = 1000; Thread.sleep(5000); System.out.println("b = " + b); } public void m2() throws Exception { Thread.sleep(2500); b = 2000; } public void run() { try { m1(); } catch(Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { TT tt = new TT(); Thread t = new Thread(tt); t.start(); tt.m2(); System.out.println(tt.b); } }
结果:
2000 b = 2000
再改一下:
1. 先执行m2, 执行完后
2. m1 执行 b=1000;
3. 主线程执行 输出b
4. m1 执行 输出b=1000;
public class TT implements Runnable { int b = 100; public synchronized void m1() throws Exception{ b = 1000; Thread.sleep(5000); System.out.println("b = " + b); } public synchronized void m2() throws Exception { Thread.sleep(2500); b = 2000; } public void run() { try { m1(); } catch(Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { TT tt = new TT(); Thread t = new Thread(tt); t.start(); tt.m2(); System.out.println(tt.b); } }
结果:
1000
b = 1000
wait必须和synchronized同时出现, 不能单独使用wait, wait是object类的方法.
wait的时候锁不归我所有, sleep的时候, 还抱着锁.
wait后需要notify叫醒, 也是object类的方法
public class ProducerConsumer { public static void main(String[] args) { SyncStack ss = new SyncStack(); Producer p = new Producer(ss); Consumer c = new Consumer(ss); new Thread(p).start(); new Thread(c).start(); } } class WoTou { int id; WoTou(int id) { this.id = id; } public String toString() { return "WoTou : " + id; } } class SyncStack { int index = 0; WoTou[] arrWT = new WoTou[6]; public synchronized void push(WoTou wt) { while(index == arrWT.length) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notifyAll(); arrWT[index] = wt; index ++; } public synchronized WoTou pop() { while(index == 0) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notifyAll(); index--; return arrWT[index]; } } class Producer implements Runnable { SyncStack ss = null; Producer(SyncStack ss) { this.ss = ss; } public void run() { for(int i=0; i<10; i++) { WoTou wt = new WoTou(i); ss.push(wt); System.out.println("生产了:" + wt); try { Thread.sleep((int)(Math.random() * 200)); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Consumer implements Runnable { SyncStack ss = null; Consumer(SyncStack ss) { this.ss = ss; } public void run() { for(int i=0; i<10; i++) { WoTou wt = ss.pop(); System.out.println("消费了: " + wt); try { Thread.sleep((int)(Math.random() * 1000)); } catch (InterruptedException e) { e.printStackTrace(); } } } }