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可以用来临时加入线程执行。

 

posted @ 2020-02-27 11:42  孤灯伴码农  阅读(...)  评论(...编辑  收藏