zoukankan      html  css  js  c++  java
  • Java:多线程

    1、什么是线程?

    在说线程之前,我们有必要了解下什么是进程,那什么是进程呢?

      进程就是当我们打开一个计算机软件或者执行一个程序时,在计算机中运行的反映,线程依托进程,而一个进程中至少有一个线程,比如JVM是一个进程,而它至少有一个主线程在CPU中执行,不然不可能启动JVM,另外也有一个垃圾回收的线程在运行。可以在任务管理器里面查看到的那些就是进程 如下:

      线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

      单线程:就比如当我们打开电脑管家或者类似的软件,执行里面的清理垃圾这个线程,只有在本次执行完成后才可以点击再执行,在本次为执行完成之前,你继续点击是没有反应的,单线程简单就是这么理解。

      多线程:如果程序中只有单线程,效率会变的很低,就好比生活中在车站的售票窗口,如果就只有一个售票窗口,这样效率特别低,但是真实却是有多个售票窗口,多线程就好比这个多售票窗口,在java中提供了并发机制,而程序员所要做的就是保证这些多线程所访问的共享数据的安全性,这就是多线程编程,线程一增多,也会越来越复杂!

    2、java多线程的实现方式

    参考http://c.biancheng.net/view/1159.html

    3、Java对于多线程的安全问题提供了专业的解决方式

    就是同步代码块。

    synchronized(对象){

      需要被同步的代码

    }

    对象如同锁。持有锁的线程可以在同步中执行。

    没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。

    同步的前提:

    1)必须要有两个或者两个以上的线程。

    2)必须是多个线程使用同一个锁。

    必须保证同步中只能有一个线程在运行。

    好处:解决了多线程的安全问题。

    弊端:多个线程需要判断锁,较为消耗资源,

    4、线程的状态

    参考https://www.runoob.com/java/java-multithreading.html

    5、CPU的随机性造成的问题

    多线程具备随机性。因为是由cpu不断的快速切换造成的。就有可能会产生多线程的安全问题。

    问题的产生的原因:

    几个关键点:

    1,多线程代码中有操作共享数据。

    2,多条语句操作该共享数据。

    当具备两个关键点时,

    有一个线程对多条操作共享数据的代码执行的一部分。还没有执行完,另一个线程开始参与执行。

    就会发生数据错误。

    解决方法:

    当一个线程在执行多条操作共享数据代码时,其他线程即使获取了执行权,也不可以参与操作。

    Java就对这种解决方式提供了专业的代码。

    同步

    同步的原理:就是将部分操作功能数据的代码进行加锁。 

    同步的表现形式

    1,同步代码块。

    2,同步函数。

    两者有什么不同:

    同步代码块使用的锁是任意对象。

    同步函数使用的锁是this

    注意:对于static的同步函数,使用的锁不是this。是 类名.class 是该类的字节码文件对象。

    涉及到了单例设计模式的懒汉式。

    同步的好处:解决了线程的安全问题。

    弊端:

    较为消耗资源。

    同步嵌套后,容易死锁。

    要记住:同步使用的前提:

    1,必须是两个或者两个以上的线程。

    2,必须是多个线程使用同一个锁。

    这是才可以称为这些线程被同步了。

    死锁代码一定会写。但开发时一定注意避免

    #第二重点:同步的所有特性    #

    Sleep() wait() notify() notifAll()

    JDK1.5 中提供了多线程升级解决方案。

    将同步Synchronized替换成现实Lock操作。

    Object中的waitnotify notifyAll,替换了Condition对象。

    该对象可以Lock锁 进行获取。

    Lock:替代了Synchronized

    lock

    unlock

    newCondition()

    Condition:替代了Object wait notify notifyAll

    await();

    signal();

    signalAll();

     生产者消费者模式示例:

    import java.util.concurrent.locks.*;
    
    public class ProducerConsumerDemo2
    {
        public static void main(String[] args)
        {
            Resource r = new Resource();
    
            Producer2 pro = new Producer2(r);
            Consumer2 con = new Consumer2(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();
    
        }
    }
    
    /*
    JDK1.5 中提供了多线程升级解决方案。
    将同步Synchronized替换成现实Lock操作。
    将Object中的wait,notify notifyAll,替换了Condition对象。
    该对象可以Lock锁 进行获取。
    该示例中,实现了本方只唤醒对方操作。
    
    Lock:替代了Synchronized
        lock
        unlock
        newCondition()
    
    Condition:替代了Object wait notify notifyAll
        await();
        signal();
        signalAll();
    */
    class Resource
    {
        private String name;
        private int count = 1;
        private boolean flag = false;
        //  t1    t2
        private Lock lock = new ReentrantLock();
    
        private Condition condition_pro = lock.newCondition();
        private Condition condition_con = lock.newCondition();
    
    
    
        public  void set(String name)throws InterruptedException
        {
            lock.lock();
            try
            {
                while(flag)
                    condition_pro.await();//t1,t2
                this.name = name+"--"+count++;
    
                System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
                flag = true;
                condition_con.signal();
            }
            finally
            {
                lock.unlock();//释放锁的动作一定要执行。
            }
        }
    
    
        //  t3   t4
        public  void out()throws InterruptedException
        {
            lock.lock();
            try
            {
                while(!flag)
                    condition_con.await();
                System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
                flag = false;
                condition_pro.signal();
            }
            finally
            {
                lock.unlock();
            }
    
        }
    }
    
    class Producer2 implements Runnable
    {
        private Resource res;
    
        Producer2(Resource res)
        {
            this.res = res;
        }
        public void run()
        {
            while(true)
            {
                try
                {
                    res.set("+商品+");
                }
                catch (InterruptedException e)
                {
                }
    
            }
        }
    }
    
    class Consumer2 implements Runnable
    {
        private Resource res;
    
        Consumer2(Resource res)
        {
            this.res = res;
        }
        public void run()
        {
            while(true)
            {
                try
                {
                    res.out();
                }
                catch (InterruptedException e)
                {
                }
            }
        }
    }

    输出结果

    中断线程

    stop方法已经过时。

    如何停止线程?

    只有一种,run方法结束。

    开启多线程运行,运行代码通常是循环结构。

    只要控制住循环,就可以让run方法结束,也就是线程结束。

    特殊情况:

    当线程处于了冻结状态。

    就不会读取到标记。那么线程就不会结束。

    当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。

    强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。

    Thread类提供该方法 interrupt();

    join:

    A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。

    join可以用来临时加入线程执行。

  • 相关阅读:
    js日期时间补零
    判断交换机性能好坏的九个因素
    [转]document.getElementById("...") is null
    ABAP数据库操作之操作语句Insert
    abap对excel处理
    选择屏幕搜索帮助
    Screen返回选择界面的问题
    ABAP 的TABLE CONTROL实践积累
    ALV的双击使用
    双击ALV调用事务代码并传入参数
  • 原文地址:https://www.cnblogs.com/GOOGnine/p/12370902.html
Copyright © 2011-2022 走看看