黑马程序员----------多线程

来源:互联网 发布:生成全排列的递归算法 编辑:程序博客网 时间:2024/04/30 22:51

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

多线程:

进程:正在进行中的程序,

多线程:进程中的程序控制单元

Jvm在启动时,首先先有一个主程序,负责程序的执行,调用的是main函数,主线程执行的代码都在main函数中

当产生垃圾时,收垃圾的过程,不需要主程序来完成,会有一个垃圾回收的线程来完成

多线程的随机性:是由于cpu快速切换线程的原因,cpu切换到哪个程序,哪个程序就会执行

返回当前线程的名称:Thread.currentThread().getName();

开启线程用到了start()方法

开始start()方法:启动了线程,并调用了run()方法

线程状态:开启start

       运行  哪个线程获得执行资格,哪个线程执行 

   冻结  sleep()  wait() natify()唤醒

   临时阻塞  具备执行资格,无执行权

         消亡 stop

创建线程的方式一:继承Thread类

步骤:继承Thread类

    覆盖run()方法

    创建Thread对象

    调用start()方法开启线程

创建线程的方式二:现象Runable接口

步骤:实现Runable接口

     覆盖run()方法

     创建实例对象   Ticket t=new Ticket();

     创建Thread对象   Thread t1=new Thread()

     将实例对象与Thread相关联 Thread t1=new Thread(t);

     调用start()方法开启线程

好处:实现Runable接口可以避免继承的局限性

多线程的安全问题:当一个线程在执行的过程中,另一条线程却参与进来,并且操作了其中的数据,导致了错误数据的产生。

安全问题产生原因:多条语句执行时,在某一时刻,被某一个线程执行时,还没有执行完,就被另一个线程执行

解决安全问题的原理:

只要将操作共享数据的语句在某一时段让一个线程执行完,在执行过程中,其他线程不能进来执行就可以解决这个问题。

用到了同步代码块synchronized

格式:synchronized(任意对象)

{执行语句}

(任意对象)是为同步代码块的锁,锁的目的是为了被同步的程序只有一个线程在执行,其他线程不能够执行

同步:解决了线程的安全问题,单相对降低了性能

定义同步的前提:必须有两个以上的线程,多个线程必须使用的是同一个锁

同步的第二种表现形式:同步函数

同步函数:定义在函数上的同步,他的锁是this锁

带有static的同步函数,他的锁是类名.class

同步代码块和同步函数大的区别:同步代码块是用的锁是任意对象,同步函数是用的锁是this锁,静态同步使用的锁是类名.class

在一个类中如果只有一个线程,可以使用同步函数,如果有过个线程,必须使用同步代码块,同步代码块比较灵活

延迟加载的单例模式,当出现安全问题时的情况

Public Single{

    privateSingle s=null;

    privateSingle(){}

    publicstatic Single getIntance(){

if(s!=null){

synchronized(Single.class){

if(s!=null){

s=new Single();

}} }return s; }}

同步死锁:同步之间相互嵌套,同步函数中有同步代码块,同步代码块中有同步函数。

线程间的通信:多个线程同时操作一个资源,但是操作的动作去不一样

将资源封装成对象

将线程执行的任务也封装成对象

等待唤醒机制:

wait:将线程冻结,释放了执行权,释放了执行资格,将线程存放到线程池中

notify:唤醒线程池中的一个线程

notify:唤醒线程池中所有的线程

需要注意的是:这些方法必须在同步中定义

        方法必须表示所属的锁

wait和sleep的区别:

wait可以指定时间亦可以不指定时间,不指定时间必须有notify或notifyAll唤醒

sleep必须指定时间,时间一到就有冻结状态变成临时阻塞状态

wait会释放执行权,会释放锁

sleep会释放执行权,但不会释放锁

线程的停止:线程停止就是停止其中run方法。方式一:在方法中定义循环标记结束,方式二:如果线程处于冻结状态,不能够读到标记,应使用Thread中interrupt方法将冻结状态强制清除,是线程运行,读到标记,结束线程

Lock接口:

解决线程安全问题使用同步,其终还是锁机制,在1.5版本后,直接将所封装成了对象,线程进入同步就开启了锁,线程结束,退出同步就释放了锁。把这些动作定义在锁中,并封装成了对象。同步时隐形的锁操作,lock是显性的锁操作,他的出现代替了同步

Lock接口中等待唤醒机制是用await(),signal(),signalAll()这些方法来完成的

例子:class Res {

    privateString name;

    privateint count = 1;

    privateLock lock = new ReentrantLock();

    privateCondition pro_con = lock.newCondition();

    privateCondition con_con = lock.newCondition();

    privateboolean falg ;

    publicvoid set(String name) {

        lock.lock();

        try{

        while(falg)

        try{pro_con.await();} catch(InterruptedException e) {}

        this.name= name + "...." + count;

        count++;

System.out.println(Thread.currentThread().getName()+ "..生成者.."+ this.name);

falg = true;

con_con.signalAll();   

    } finally{

    lock.unlock();

    }

}

public voidget() {

    lock.lock();

    try{

    while(!falg)

    try{con_con.await();} catch(InterruptedException e) {}

    System.out.println(Thread.currentThread().getName() + "..消费者.."+ this.name);

    falg = false;

    pro_con.signalAll();       

    } finally{

    lock.unlock();

    }

    }

}

class Producer implementsRunnable {

    privateRes r;

    publicProducer(Res r) {

        super();

        this.r= r;

    }

    @Override

    publicvoid run() {

        while(true) {

            r.set("面包");

        }

    }

}

class Consumer implementsRunnable {

    privateRes r;

    publicConsumer(Res r) {

        super();

        this.r= r;

    }

    @Override

    publicvoid run() {

        while(true) {

            r.get();

        }

    }

}

public classTest3 {

    publicstatic void main(String[] args) {

    /* 生产者消费者的多线程 */

    Res r = new Res();

    Producer pro = new Producer(r);

    Consumer con = new Consumer(r);

    Thread t0 = new Thread(pro);

    Thread t1 = new Thread(pro);

    Thread t2 = new Thread(con);

    Thread t3 = new Thread(con);

    t0.start();

    t1.start();

    t2.start();

    t3.start();

    }

}

 

 

 

 

 

 

       


0 0
原创粉丝点击