黑马程序员_多线程

来源:互联网 发布:淘宝买家已付款钱在哪 编辑:程序博客网 时间:2024/06/05 15:51

  ------- android培训java培训、期待与您交流! ----------


一 进程和线程概念
1 进程:进程就是正在执行的程序,每个进程执行都有一个执行顺序,该顺序就是一个控制单元或执行路径。
2 线程:线程就是进程中的一个独立的控制单元,线程控制着进程的执行。一个进程中至少有一个线程。
3 java虚拟机启动的时候会启动一个进程,该进程会有一个线程控制者程序的执行,线程执行的代码存在main函数中,该线程称为主线程。
4 多线程:一个进程能有多个线程,多线程能提高效率。


二 线程的几种状态:
(1)线程创建:创建Thread或Thread子类对象
(2)线程运行:具备运行资格,有执行权,方法start()
(3)线程阻塞:具备运行资格没有执行权
(4)线程冻结:没有执行资格,通过sleep(int time);wait();方法
(5)线程消亡:stop();程序结束


三 创建线程(两种方式)
1 继承Thread类,复写run()方法,线程运行的代码在run()方法中。调用start()方法执行线程。
(1)run()仅仅只是调用run()方法而没有执行线程
(2)start()执行线程并调用run()方法
例如:

class XianCheng extends Thread{public void run(){System.out.println("线程运行");}}class ThreadDemo{public static void main(String[] args){XianCheng xc=new XianCheng();//创建线程xc.start();//执行线程}}

2.创建类实现Runnable接口,覆盖run()方法,创建Thread线程对象,并将Runnable接口子类对象作为参数传给Thread的构造方法,调用Thread对象start()方法
例如:

class XianCheng implements Runnable{public void run(){System.out.println("线程运行");}}class ThreadDemo{public static void main(String[] args){XianCheng xc=new XianCheng();//创建Runable子类对象Thread t=new Thread(xc);//创建线程并将Runable的子类对象传进来t.start();//执行线程}}

3 二种方式的区别
(1)继承Thread类方法,有继承的局限性,因为java只支持单继承。多线程运行的代码放在Thread类的子类的run()方法中。
(2)实现Runnable接口方法,java支持多实现,所以用这种方法提高了扩展性。此方法多线程运行的代码放在Runnable接口子类的run()方法中。

4 线程同步的方式
(1)同步代码块,同步代码块用的锁是任意对象都可以
     格式:
synchronized(对象//任意对象)
{
需要被同步的语句;
}
(2)同步函数,将synchronized关键字放在函数的返回值前面,同步函数用的锁是this
     静态同步函数,静态同步函数用的锁是该类的字节码文件对象 类名.class
线程同步例子:

class ThreadDemo{public static void main(String[] args) {//创建Runnable接口子类对象SaleTicket st=new SaleTicket();//创建线程将对象传给Thread类的构造方法Thread t1=new Thread(st);Thread t2=new Thread(st);Thread t3=new Thread(st);Thread t4=new Thread(st);//线程执行t1.start();t2.start();t3.start();t4.start();}}class SaleTicket implements Runnable{//定义100张票private int ticket=100;//覆盖run()方法public void run(){//无线循环while(true){//加同步,同步的锁是SaleTicket类的文件对象synchronized(SaleTicket.class){if(ticket>0){//制作一个线程安全隐患try{Thread.currentThread().sleep(5);} catch(Exception e){}System.out.println(Thread.currentThread().getName()+"正在售票第"+ticket--+"张票");}}}}}

5 懒汉式的线程同步

代码如下:

class Single{private Single(){}//将构造函数私有不给外界创建对象private static Single s=null;//本类创建对象,用静态修饰,方便getInstance()访问public static Single getInstance(){//双层判断,只要s创建过对象就不再判断锁了,稍微高效if(s==null){//在这里加锁,防止多个线程同时执行下面的语句synchronized(Single.class){//如果为空,创建对象if(s==null)s=new Single();}}return s;}} 

6 死锁,同步中嵌套同步很容易发生死锁

代码示例:

public void run(){//如果一个线程执行if中代码,而另一个线程执行else代码if(flag){//此线程a锁中嵌套b锁synchronized(Mylock.locka){System.out.println("if locka");synchronized(Mylock.lockb){System.out.println("if lockb");}}}else{//此线程b锁中嵌套a锁,此时就很容易发生死锁synchronized(Mylock.lockb){System.out.println("else lockb");synchronized(Mylock.locka){System.out.println("else locka");}}}}

五 通信间的线程
1 Object中应用线程的方法
  wait(),notify(),notifyAll()这些方法要使用在同步中。

2 定义在Object的原因
(1)这些方法在操作线程时,都必须标识他们所操作线程中的锁
(2)只有同一个锁上的线程等待,能被同一锁的线程唤醒
(3)而锁可以是任意对象,所以定义在Object中

3 等待中的线程在线程池中,一般线程唤醒的是线程中的第一个线程
例子:创建两个线程,一个负责赋值,一个赋值取值,操作同一资源对象。代码如下:

class  ThreadDemo{public static void main(String[] args) {//创建资源对象Res r=new Res();//创建两个线程,一个负责给资源赋值,一个负责取值new Thread(new Input(r)).start();new Thread(new Output(r)).start();}}//定义一个资源类class Res{private String name;private String sex;private boolean flag;//同步函数public synchronized void set(String name,String sex){//判断标记,资源中没值就赋值,有值线程就等待if(flag)try{wait();} catch(Exception e){}this.name=name;this.sex=sex;flag=true;//赋值之后把标记改为true,代表有值了notify();//把对方唤醒}//同步函数public synchronized void get(){//判断标记,资源中有值就取,没值线程就等待if(!flag)try{wait();} catch(Exception e){}System.out.println(name+":::"+sex);flag=false;//取值后把标记改为falsenotify();//唤醒对方}}//定义一个赋值的线程class Input implements Runnable{//将资源传递给构造方法private Res r;Input(Res r){this.r=r;}public void run(){int num=0;while(true){if(num==0)r.set("lisi","man");elser.set("李四","男");num=(num+1)%2;}}}//定义一个取值的线程class Output implements Runnable{//将资源传递给构造方法private Res r;Output(Res r){this.r=r;}public void run(){while(true){r.get();}}}

4 JDK1.5版本之后,提供了多线程升级解决方案
(1)将synchronized变为显示的Lock
(2)将Object中的wait(),notify(),notifyAll()替换成了Condition对象,更灵活的应用等待唤醒机制


六 操作线程的其他方法
1 停止线程:stop()(此方法已经过时),只有一种方法,就是run()方法结束,一般run()方法中,定义的都是循环语句,所以我们可以控制循环使线程结束。

2 中断线程:interrupt(),此方法可以将处于冻结状态的线程强制回到运行状态(清除线程的冻结状态)

3 守护线程:setDeamon()后台线程,当前台线程结束后,后台线程自动结束。此方法必须在线程执行前调用。

4 等待线程停止:jion()方法,放某个线程执行到join()方法时,该线程会冻结,等到调用join()方法的线程结束,该线程才回到运行状态。

5 优先级:setPriority(),此方法可以设置线程的优先级,优先级越高,CPU执行该线程的频率越高。默认是5。

6 yield():临时停止,暂停线程




0 0
原创粉丝点击