多线程基础

来源:互联网 发布:云计算一姐 编辑:程序博客网 时间:2024/05/16 18:41

1.进程与线程的区别

进程是cpu执行的一个可执行程序,cpu通过进程间的快速切换实现了让所有的程序看似都同时在运行(单核)

线程是进程的执行流程,一个进程中至少有一个线程,每个线程可以得到一小段的执行时间(像时间片轮转法)

执行完这个事务就去执行下一个事务,这样使得一个程序看起来可以同时处理多个事务


2.线程栈模型

线程以栈的形式存储,main方法创建的时候会开启一个主线程,即开启了一个栈,当创建一个线程的时候,使用.start()方法的

时候,再创建一个执行栈,两个栈同时运行,就形成了多线程。


3.开启线程的两种方法

实现Runnable接口,覆盖run方法(推荐)

继承Thread类,覆盖run方法

两种方法的区别:Runnable避免了单继承的局限性


4.线程状态转换

创建-就绪-执行-阻塞-死亡


5.sleep方法

<span style="font-size:14px;"><strong>package Myday3;/** * 一个计数器,计数到100,在每个数字之间暂停1秒,每隔10个数字输出一个字符串 */public class MyThread implements Runnable {    @Overridepublic void run() {for(int i=0;i<101;i++){if(i!=0&&i%10==0)System.out.println("输出");try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(i);}}    public static void main(String[] args) {MyThread mt = new MyThread();Thread t1 = new Thread(mt);t1.start();}}</strong></span>

6.线程的优先级和线程让步

线程的优先级在(1--》10)通过Thread.getPriority()实现,例如

Thread t= new Thread();

t.setPriority(10);

t.start();

线程让步是通过Thread.yield()方法实现的,作用:暂停当前线程让其他线程执行


不管是线程优先级还是线程让步都无法真正完全控制住线程,被让步和低优先级的线程仍然有机会被执行到


7.join()方法

Thread的非静态方法join()让一个线程B“加入”到另外一个线程A的尾部。在A执行完毕之前,B不能工作。例如:
        Thread t = new MyThread();
        t.start();
        t.join();
另外,join()方法还有带超时限制的重载版本。 例如t.join(5000);则让线程等待5000毫秒,如果超过这个时间,则停止等待,变为可运行状态。
join()方法可以保证当前的线程停止,让其他线程先执行,如若其他线程死亡,不暂停该线程
 8.同步
同步的前提:必须有多个线程,多个线程必须使用同一个锁,同步中必须只有一个线程运行
好处:解决多线程的安全问题,弊端:每次都得判断锁,消耗资源
同步方法:同步代码块,同步函数,锁默认为this,静态为ClassName.class
9.死锁
产生原因:同步嵌套同步,且锁不一样
class Test implements Runnable{private boolean flag;Test(boolean flag){this.flag=flag;}public void run(){if(flag){synchronized(Mylock.locka){System.out.println("if locka");synchronized(Mylock.lockb){System.out.println("if lockb");}}}else{synchronized(Mylock.lockb){System.out.println("else lockb");synchronized(Mylock.locka){System.out.println("else locka");}}}}}class Mylock{static Object locka=new Object();static Object lockb=new Object();}class  DeadLockTest{public static void main(String[] args) {Thread t1=new Thread(new Test(true));Thread t2=new Thread(new Test(false));t1.start();t2.start();}}

10.多线程之间的通信
    wait(),notify(),notifyAll() 都使用在同步中,
   因为要对持有锁的线程进行操作,也只有同步中有锁

   这些方法定义在Object中,因为每一个对象均可以为锁
   等待和唤醒的必须是同一把锁
只有一个生产者和一个消费者的时候
使用If(flag),notify();
生产者和消费者模型注意flag
注意while(flag),notifyAll();

生产者消费者模型
一个生产者和一个消费者
package day4;class Resource{private String name;private int count=1;private boolean flag=false;public synchronized void set(String name){while(flag)try{wait();}//使用wait会抛异常catch(Exception e){}this.name=name+"--"+count++;System.out.println(Thread.currentThread().getName()+"..生产者"+this.name);flag=true;this.notifyAll();}public synchronized void out(){while(!flag)try{wait();}//使用wait会抛异常catch(Exception e){}System.out.println(Thread.currentThread().getName()+"..消费者"+this.name);flag=false;this.notifyAll();}}class Produce implements Runnable{private Resource res;Produce(Resource res){this.res=res;}public void run(){while(true){res.set("商品+");}}}class Consumer implements Runnable{private Resource res;Consumer(Resource res){this.res=res;}public void run(){while(true){res.set("消费+");}}}class PCDemo{public static void main(String[] args) {Resource r=new Resource();Produce pro=new Produce(r);Consumer con=new Consumer(r);Thread t1=new Thread(pro);Thread t2=new Thread(pro);Thread t3=new Thread(con);Thread t4=new Thread(con);t1.start();t2.start();t3.start();t4.start();System.out.println("Hello World!");}}
多个生产者和多个消费者
<span style="font-size:14px;">package Myday3;class Source{int count=0;private String name;boolean flag = false;public void set(){synchronized(this){while(flag)try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"生产"+(++count));    flag=true;this.notifyAll();}}public void out(){synchronized(this){while(!flag)try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"消费"+count);flag=false;this.notifyAll();}}}class Produce implements Runnable{private Source sr;Produce(Source sr){this.sr = sr;}public void run(){while(true)sr.set();}}class Consumer implements Runnable{private Source sr;Consumer(Source sr){this.sr = sr;}@Overridepublic void run() {while(true)sr.out();}} class Lock { public static void main(String[] args){ Source sr = new Source(); Produce pd1 = new Produce(sr); Produce pd2 = new Produce(sr); Consumer con1 = new Consumer(sr); Consumer con2 = new Consumer(sr); new Thread(pd1).start(); new Thread(pd2).start(); new Thread(con1).start(); new Thread(con2).start();  }}</span>

jdk1.5提供了多线程的解决方案
将synchronized替换成了Lock
将wait notify notifyAll替换成了condition,该对象通过lock获得。
改进版
<span style="font-size:14px;">class Resource{private String name;private int count=1;private boolean flag=false;private Lock lock=new ReentrantLock();//创建锁private Condition con_1=lock.newCondition();private Condition con_2=lock.newCondition();public  void set(String name)throws InterruptedException{lock.lock();try{while(flag)con_1.await();this.name=name+"--"+count++;System.out.println(Thread.currentThread().getName()+"..生产者"+this.name);flag=true;con_2.signal();}finally{lock.unlock();}}public  void out(){lock.lock();try{while(!flag)try {con_2.await();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName()+"..消费者"+this.name);flag=false;con_1.signal();}finally{lock.unlock();}}}class Produce implements Runnable{private Resource res;Produce(Resource res){this.res=res;}public void run(){while(true){try{res.set("商品+");}catch (InterruptedException e){}}}}class Consumer implements Runnable{private Resource res;Consumer(Resource res){this.res=res;}public void run(){while(true){try{res.set("消费+");}catch (InterruptedException e){}}}}class  PCDemo{public static void main(String[] args) {Resource r=new Resource();Produce pro=new Produce(r);Consumer con=new Consumer(r);Thread t1=new Thread(pro);Thread t2=new Thread(pro);Thread t3=new Thread(con);Thread t4=new Thread(con);t1.start();t2.start();t3.start();t4.start();System.out.println("Hello World!");}}</span>

11.守护线程
public final void setDaemon(boolean on)将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。    
  该方法必须在启动线程前调用。    

  该方法首先调用该线程的 checkAccess 方法,且不带任何参数。这可能抛出 SecurityException(在当前线程中)。

12.停止线程
class StopThread implements Runnable{private boolean flag=true;public void run(){while(flag ){try{wait();}//使用wait会抛异常catch(InterruptedException e){System.out.println(Thread.currentThread().getName()/*.toString()*/+"...Exception");}System.out.println(Thread.currentThread().getName()+"...run");}}public void changeFlag(){flag=false;}}class  StopThreadDemo{public static void main(String[] args) {StopThread st=new StopThread();Thread t1=new Thread(st);Thread t2=new Thread(st);t1.setDaemon(true);t2.setDaemon(true);//后台线程,守护线程t1.start();t2.start();int num=0;while(true){if(num++==60){//st.changeFlag();    t1.interrupt();t2.interrupt();break;}System.out.println(Thread.currentThread().getName()+"..."+num);}System.out.println("over");}}








0 0