• 黑马程序员_Java学习日记num8


    ------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
    学习内容:线程的创建;线程的同步;线程间的通信;操纵线程的常见函数
     
    一、线程的创建
    1,线程的创建方式一
    1)定义一个类并且继承Thread
    2)覆写其中的run()方法,run()方法中存放的是线程的运行代码
    3)调用线程的start()方法,该方法启动线程,并且调用run()方法
     
    2,线程的创建方式二
    1)定义一个类实现Runnable接口
    2)覆写Runnable接口的run()方法,将线程要运行的代码存放在该run()方法中
    3)创建实现了Runnable接口的子类的实例对象,并将它作为实际参数传递给Thread类的构造函数
    4)调用Thread类的start()方法,开启线程并且调用Runnable接口子类中的run方法
     
    3,两种创建方式的总结
    1)实现方式建立线程,避免了java语言单继承的局限。所以在定义线程时,建议使用实现方式。
    2)继承Thread方式中,线程的运行代码存放在Thread子类的run()方法中。实现Runnable方式中,线程代码存放在Runnable接口的子类的run()方法。
     
    二,线程同步
     
    1,同步问题
    当多个线程操作共享数据时,如果没有加以同步限制,可能出现这样的情况,一个线程在操作共享数据一部分时,另外的线程也进来操作共享数据,这样就造成了数据的不一致,出现了错误。
     
    2,解决办法
    对于操作共享数据的语句,只能让一个线程执行完毕后,另外线程不可以参与执行。也就是对于共享数据,每次只能有一个线程操纵。java提供了这种同步方式 同步代码块,同步函数。
     
    3,同步的前提
    必须存在两个或者两个以上的线程
    必须是多个线程使用同一把锁
     
    4,同步的利弊
    利:解决了多线程的安全问题
    弊:多线程需要判断锁,较为消耗资源。(这个较为消耗资源是在允许的范围内)
     
    5,关于同步的锁的问题
    同步代码块需要手动指定一个对象当做锁。非静态同步函数的锁是this;静态同步函数的锁是该方法所在类的字节码文件对象。
     
    6,死锁
    同步中嵌套同步而锁不同。用比较专业的术语说就是:相互抢夺资源但是又不释放自己的资源,造成相互等待的情况
     
    7,线程同步的举例
     
    需求:通过实现方式定义四个线程,操作共享数据tick,每操作一次tick值减一并且打印一次。
    class Ticket implements Runnable
    {
    private  int tick = 1000;
    Object obj = new Object();
    public void run()
    {
    while(true)
    {
    synchronized(obj)
    {
    if(tick>0)
    {
           System.out.println(Thread.currentThread().getName()+"。。。。。"+ tick--);
    }
    }
    }
    }
    }
     
     
    class  TicketDemo2
    {
    public static void main(String[] args) 
    {
     
    Ticket t = new Ticket();
     
    Thread t1 = new Thread(t);
    Thread t2 = new Thread(t);
    Thread t3 = new Thread(t);
    Thread t4 = new Thread(t);
    t1.start();
    t2.start();
    t3.start();
    t4.start();
     
     
    }
    }
     
    三、线程间的通信
     
    1,线程间通信
    其实就是多个线程在操作一个资源,但是操作的动作不同。
     
    2,等待唤醒机制
    wait(),notify()以及notifyAll()都使用在同步中,因为要对持有锁(监视器)的线程操作,所以要使用在同步中,因为只有同步才具有锁。
     
    3,为什么wait(),notify()以及notifyAll()都要定义在Object类中呢?
    因为这些方法是操作同步线程时,都必须要标识他们所操作线程持有的锁。只有同一个锁上的被等待线程可以被同一个锁上的notify唤醒,不可以对不同锁中的线程唤醒,也就是说,等待和唤醒必须使用同一把锁。而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。
     
    4,JDK1.5中提供的操作线程的新特性。
    将同步Synchronized替换成了现实lock操作
    将object类中的wait(),notify(),notifyAll()替换了Condition对象,该对象可以有lock锁获得。
    对于最后的解锁语句unlock一般都在finally语句中执行
    通过这种方式,可以显式的加锁,显式的解锁;还有一个好处,就是根据Condition对象的不同,可以随意的指定await那个线程,随意的指定signal那个线程。
     
    5,一个关于生产者消费者的示例
    需求:定义一个资源,然后定义两个生产者,两个消费者来操作共享资源,只有生产出来,才能消费,并且只能消费一次。生产者消费者是一个经典的线程间通信示例,代码如下:
     
    package Test;
     
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
     
    class Resource//定义资源
    {
    private String name;
    private int count = 1;
    private boolean flag = false;
    private Lock lock = new ReentrantLock();//定义锁
    private Condition condition_set = lock.newCondition();//定义生产者监视器对象
    private Condition condition_get = lock.newCondition();//定义消费者监视器对象
    public void set(String name)
    {   
    lock.lock();
    try
    {
    while(flag)
    condition_set.await();
    this.name = name + count++;
    System.out.println("生产者"+"....."+this.name);
    this.flag = true;
    condition_get.signal();
    }
    catch(InterruptedException e)
    {
    e.printStackTrace();
    }
       finally
       {
        lock.unlock();//释放锁,一般释放锁都在这里
       }
    }
    public void get()
    {
    lock.lock();
    try
    {  
    while(!flag)
    condition_get.await();
    System.out.println("消费者"+"....."+this.name);
    this.flag = false;
    condition_set.signal();
    }
    catch (InterruptedException e) {
    e.printStackTrace();
    }
    finally
    {
    lock.unlock();
    }
    }
    }
     
    class Producer implements Runnable//定义生产者,实现Runnable接口
    {
    private Resource res;
    Producer(Resource res)
    {
    this.res = res;
    }
    public void run()
    {
    while(true)
    {
    res.set("商品");
    }
    }
    }
     
    class Consumer implements Runnable//定义消费者,实现Runnable接口
    {
    private Resource res;
    Consumer(Resource res)
    {
    this.res = res;
    }
    public void run()
    {
    while(true)
    {
    res.get();
    }
    }
    }
    public class ProducerConsumerDemo {
     
    public static void main(String[] args)
    {
    Resource res = new Resource();
    Producer pro = new Producer(res);
    Consumer con = new Consumer(res);
    Thread t1 = new Thread(pro);
    Thread t2 = new Thread(con);
    Thread t3 = new Thread(pro);
    Thread t4 = new Thread(con);
    t1.start();
    t2.start();
    t3.start();
    t4.start();
    }
     
    }
     
    四、操纵线程的几个函数
     
    1,interrupt()  停止线程
    停止线程的方法是stop(),但是这个方法已经过时,不能使用。那只剩下一种,run()方法结束。开启多线程运行代码通常是循环结构,只要控制住循环,就可以让run方法结束,也就是线程结束
    那interrupt()这个方法是干什么呢?乍一看,interrupt不是中断嘛,就是把正在运行的线程中断停止掉。错!错!!。interrupt的中断是这个意思,当线程处于wait啊,sleep啊,join啊等状态是,她中断他们的冻结状态,使其回到运行状态,然后操纵run方法中的循环,控制其条件结束线程
     
    2,setDemon() 守护线程  也就是创建守护线程
    守护线程的特点是:当前台线程全部结束时,后台线程也随之结束;嘿嘿,因为前台线程结束后,JVM也跟着exit了。
    定义后台线程的要注意:setDemon()方法需要在start()方法之前声明,也就是线程启动前调用。
     
    3,join()方法
    join()方法是,当一个线程执行了另外的一个线程的join方法时,这个线程就wait了,另外的那个线程就加入到线程运行的队列中了 ,这个被wait的线程只有另外的那个线程运行完毕有才被唤醒向下执行。 
     
    4,setPriority()方法
    setPriority()方法是用于设置线程的优先级的 。优先级共10个级别(1--10)。主线程和其他线程默认的优先级都是5;
     
    5,yield()方法
    yield()方法和join()的方法有点相似,但是实现的作用是相反的。线程执行了yield()方法后,会暂停正在执行的这个线程对象,执行其他线程。
     
    6,toString()
    toString() 这个方法是定义在Object类中,功能是打印对象的字符串。而现在他定义在了线程类中,她的功能被复写为打印线程的名称,线程的优先级,线程的线程组。
  • 相关阅读:
    初识机器学习——吴恩达《Machine Learning》学习笔记(十二)
    初识机器学习——吴恩达《Machine Learning》学习笔记(十一)
    初识机器学习——吴恩达《Machine Learning》学习笔记(十)
    初识机器学习——吴恩达《Machine Learning》学习笔记(九)
    初识机器学习——吴恩达《Machine Learning》学习笔记(八)
    初识机器学习——吴恩达《Machine Learning》学习笔记(七)
    初识机器学习——吴恩达《Machine Learning》学习笔记(六)
    初识机器学习——吴恩达《Machine Learning》学习笔记(五)
    PHP面向对象之php数据对象(PDO)——图书查看管理
    刮刮乐
  • 原文地址:https://www.cnblogs.com/Rebecca-gg/p/4465864.html
Copyright © 2020-2023  润新知