基本概念 线程是一个程序内部的顺序控制流
Java的线程是通过java.lang.Thread类来实现的。main函数是一个主线程,用户可以通过创建Thread的实例来创建新的线程。每一个线程都必须实现run方法。通过Thread类的start方法来启动一个线程。
两种方式实现,一种是线程类实现Runnable接口;二种就是定义一个Thread的子类并重写其run方法。
public class TestThread1 { public static void main(String args[]) { Runner1 r = new Runner1(); r.start(); //r.run(); //Thread t = new Thread(r); //t.start(); for(int i=0; i<100; i++) { System.out.println("Main Thread:------" + i); } } } //class Runner1 implements Runnable { class Runner1 extends Thread { public void run() { for(int i=0; i<100; i++) { System.out.println("Runner1 :" + i); } } }以下是几个线程控制的基本方法
用stop或者其他方法直接切断线程是很暴力的是很不好的,这里介绍一种比较好的结束线程的办法。巧妙的用到一个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; } }线程同步 线程同步这个问题很重要,会衍生很多锁的问题。也是两种方式上锁,一种是直接在方法上上锁,另一种就是锁对象。
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的线程"); //} } }死锁 假如两个线程都需要两个资源才能完成,A线程把a资源锁定等待b资源,B线程把b资源锁定等待a资源。这样就会形成死锁,所以我们要把锁定义到最大化就是锁定整个对象,就是专业术语说锁的粒度要尽量大。
public class TT implements Runnable { int b = 100; public synchronized void m1() throws Exception{ //Thread.sleep(2000); 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 这段程序也是先进的m2。
package yanning; public class TT implements Runnable { int b = 100; public synchronized void m1() throws Exception{ System.out.println(2); //Thread.sleep(2000); b = 1000; Thread.sleep(5000); System.out.println("b = " + b); } public synchronized void m2() throws Exception { System.out.println(1); 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); } }这段代码输出的结果是 1 2000 2 b = 1000
package yanning; public class TT implements Runnable { int b = 100; public synchronized void m1() throws Exception{ //System.out.println(2); //Thread.sleep(2000); b = 1000; Thread.sleep(5000); System.out.println("b = " + b); } public synchronized void m2() throws Exception { //System.out.println(1); 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 锁是锁住了,但是tt那个线程执行的快一些,先进入了m2。
所以说线程同步是一个很复杂的问题,我们得仔细推敲。而且我个人觉得跟电脑的运行速度还是有关系的。其他线程可以自由访问没有加同步的任何方法,并且会产生数据不一致的现象。如果要保护好某一类的同步对象,必须要对该对象所有的方法考虑加不加同步,加了同步很有可能效率会变低,不加同步很有可能造成数据不一致的现象。
优先级 我的理解就是CPU优先让哪个线程执行嘛,比较单CPU其实是假的多线程,就是因为CPU运算速度比较快,所以就一个线程让你执行一下,就像是多线程在执行一样。
生产者与消费者问题【经典问题】
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<20; 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<20; i++) { WoTou wt = ss.pop(); System.out.println("消费了: " + wt); try { Thread.sleep((int)(Math.random() * 1000)); } catch (InterruptedException e) { e.printStackTrace(); } } } }