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 abcdei am abcdei am abcdei am abcdei am abcdei am abcdei am abcdei am abcdei am abcdei am abcdei am main threadi am main threadi am main threadi am main threadi am main threadi am main threadi am main threadi am main threadi am main threadi 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=1flag=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(); }}
结果:
1000b = 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); }}
结果:
2000b = 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(); } } }}