JAVA学习-进程,多线程,Thread类和Runnable接口,多线程程序的安全,synchronized,lock,等待和唤醒

进程

正在运行的程序,系统进行资源分配和调用的独立单位

线程:进程中的单个顺序控制流,是一条执行路径
单线程,多线程:一个进程有单个还是多个执行路径

多线程的实现方式1-继承Thread类

多线程第一种实现方式

设置和获取线程名称

getName
setName

线程调度

1、分时调度模型
2、抢占式调度模型:优先让优先级高的线程使用CPU;(JAVA使用的方式)
返回优先级:
public final int getPriority​():返回此线程的优先级。
public final void setPriority​(int newPriority)
更改此线程的优先级。(默认是5,范围是1-10之间)
代码实例:
申明一个实现Thread接口的类

//继承Thread方法
public class duoxiancheng extends Thread {
    
    
    @Override //重写run方法
    public void run() {
    
    
        for(int i = 0; i<100; i++){
    
    
            System.out.println(getName()+":"+i);
        }

运行类:

        duoxiancheng d1 = new duoxiancheng();
        duoxiancheng d2 = new duoxiancheng();
        duoxiancheng d3 = new duoxiancheng();
        d1.setName("shouhu1");
        d2.setName("shouhu2");
        d3.setName("laiha");
        d1.start();
        d2.start();
        d3.start();

线程控制

线程控制方法
setDeamon:将线程设置为守护线程(非主线程,副线程),如果主线程结束,当运行线程都是守护线程的时候,JAVA虚拟机退出

线程全生命周期

线程全生命周期

实现多线程方法2- 实现Runnable接口的方式

runnable
Runnable接口由任何类实现,其实例将由线程执行。
实现Runnable类Thread通过实例化一个Thread实例并将其自身作为目标来运行,而无需子类化Thread。
在大多数情况下,如果您仅计划覆盖run()方法,而不使用其他Thread方法,则应使用Runnable接口。
Thread​(Runnable target, String name) 分配一个新的 Thread对象。
创建Thread类对象后,把线程对象作为构造方法的参数
代码实例:
实现runnabl接口:

public class runable implements Runnable{
    
    

    @Override
    public void run() {
    
    
        for(int i=0;i<100;i++)
        System.out.println(Thread.currentThread().getName()+":"+i);
    }

主程序:

        runable ra = new runable();

        Thread tr1 = new Thread(ra,"meimei");
        Thread tr2 = new Thread(ra,"keke");
        
        tr1.start();
        tr2.start();

Runnable相比Thread的好处

1、避免了JAVA单继承的局限性
2、适合多个相同程序的代码去处理同一个资源的情况,把线程和程序的代码、数据有效分离,较好的体现了面向对象的思想。

多线程程序的安全

安全保证:把多条语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行;JAVA提供了同步代码块的方式来解决

同步代码块

好处:用synchronized锁住到条语句块,可以解决多线程的数据安全问题;
弊端:当线程很多时,由于每个线程都会去判断同步的锁,会耗费不少资源;

private int tickets = 1000;
//设定同一把锁
    private Object obj = new Object();

    @Override
    public void run() {
    
    
        while (true) {
    
    
        //锁线程
            synchronized (obj) {
    
    
                if(tickets>0) {
    
    
                         try {
    
    
                         //休息100MS便于其他线程抢到CPU
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets +"张票");
                        tickets --;
                }
            }
        }
    }

测试类:

        runable ra = new runable();

        Thread tr1 = new Thread(ra,"窗口一");
        Thread tr2 = new Thread(ra,"窗口二");
        Thread tr3 = new Thread(ra,"窗口三");

        tr1.start();
        tr2.start();
        tr3.start();

同步方法

同步普通方法:
修饰符 synchronized 返回值类型 方法名(方法参数);
把synchronized关键字加到方法上;同步方法的锁对象是:this;
同步静态方法:
修饰符 static synchronized 返回值类型 方法名(方法参数);
同步静态方法的锁对象是:类名.class

线程安全的类

StringBuffer:

线程安全,可变的字符序列。
这个类已经被一个等同的类补充了,它被设计为使用一个线程, StringBuilder 。 通常应该使用StringBuilder类,因为它支持所有相同的操作,但它更快,因为它不执行同步。

Vector:

从Java 2平台v1.2开始,该类改进了List接口,使其成为Java Collections Framework的成员。 与新的集合实现不同, Vector被同步。 如果不需要线程安全的实现,建议使用ArrayList代替Vector

HashTable:

该类实现了一个哈希表,它将键映射到值。 任何非null对象都可以用作键值或值。
从Java 2平台v1.2开始,该类进行了改进,实现了Map接口,使其成为Java Collections Framework的成员。 与新的集合实现不同, Hashtable被同步。 如果不需要线程安全的实现,建议使用HashMap代替Hashtable

Lock锁

lock​() 获得锁。
unlock​() 释放锁。
Lock是接口不能直接被实例化,采用实现类ReentrackLock来实例化
代码实例:
线程类:

public class runable implements Runnable{
    
    
    private int tickets = 100;
    private Lock lock = new ReentrantLock();//实例化

    @Override
    public void run() {
    
    
        while (true) {
    
    
            try {
    
    //用try finally的语法,try中有代码问题不影响锁操作
                lock.lock();//加锁
                {
    
    
                    if (tickets > 0) {
    
    
                    try {
    
    
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                        System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                        tickets--;
                    }
                }
            }finally {
    
    
                lock.unlock();//释放锁
            }
        }
    }
}

测试类:

        runable ra = new runable();

        Thread tr1 = new Thread(ra,"窗口一");
        Thread tr2 = new Thread(ra,"窗口二");
        Thread tr3 = new Thread(ra,"窗口三");

        tr1.start();
        tr2.start();
        tr3.start();

生产者和消费者模型

需要在同步里使用;等待和唤醒方法
等待唤醒
wait后,需要其他线程继续操作的情况下,要进行notify或notifyAll唤醒操作

猜你喜欢

转载自blog.csdn.net/weixin_52723971/article/details/111296897