Java多线程基础

一、概念

并发

并发的实质是一个或多个物理CPU,在若干个程序之间多路复用,并发性是对有限物理资源强制行使,多用户共享以提高效率【例如:两个或多个事件在同一时间段内发生:边打游戏边看电视】

并行

同时发生两个并发事件【例如:同一时刻发生,你和朋友一起打游戏】

进程

一个在内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程可以有多个线程【例如:QQ.exe】

线程

进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据

所以系统中会存在:多线程并发【多个任务 同一时间段争CPU】;此外:java本身就是多线程的

二、实现

1、继承Thread类

public class TestDemo {
    public static void main(String[] args) {
        ThreadDemo threadDemo = new ThreadDemo();
        // start 与 run 区别
        threadDemo.start(); // 实现多线程运行,无需等待run方法体执行完毕,可以直接向下执行
        threadDemo.run();   // 串行运行,Run 方法运行结束,此线程终止,才可以继续向下执行
    }
}
// 继承Thread类 但是存在:java单继承 不易扩展的问题
class ThreadDemo extends Thread{
    @Override
    public void run() {
        System.out.println("ThreadDemo方法逻辑");
    }
}

2、实现Runnable接口

public class TestDemo {
    public static void main(String[] args) {

        RunnableDemo runnableDemo = new RunnableDemo();
        // 多个线程同时执行runnableDemo,可以共享index变量,继承Thread类需要将变量置为static
        Thread t1 = new Thread(runnableDemo,"线程1");
        Thread t2 = new Thread(runnableDemo,"线程2");
        Thread t3 = new Thread(runnableDemo,"线程3");
        t1.start();t2.start();t3.start();
    }
}
// 优点:适合资源共享;避免单继承的局限性;
class RunnableDemo implements Runnable{
    private Integer index = 3;
    @Override
    public void run() {
        // Runnable的run()方法不能抛出异常,必须在run()捕获;
        try{
            System.out.println(Thread.currentThread().getName()+": RunnableDemo方法逻辑"+index--);
        }catch (Exception e){
            
        }
    }
}
//线程3: RunnableDemo方法逻辑3
//线程1: RunnableDemo方法逻辑2
//线程2: RunnableDemo方法逻辑1

3、实现Callable接口

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class TestDemo {
    public static void main(String[] args) throws Exception {
        CallableDemo callableDemo = new CallableDemo();
        // 执行Callable 任务后,可以获取一个 Future 的对象,
        FutureTask<Integer> future = new FutureTask<Integer>(callableDemo);
        new Thread(future).start();
        // 在 Future 对象上调用 get 就可以获取到 Callable 任务返回的 数据 了
        System.out.println(future.get());
    }
}
// 实现Callable接口,重写call()方法来实现一个线程;
class CallableDemo implements Callable<Integer> {
    private int index = 10;
    // Callable可以在任务结束后提供一个返回值;
    @Override
    // Callable接口中的call()方法可以抛出异常;
    public Integer call() throws Exception {
        return getSum(index);
    }
    public Integer getSum(int x){
        if (x==0){
            return 0;
        }
        return x+getSum(--x);
    }
}
// 55

三、常用方法

方法名

说明

setPriority(int newPriority)

设置线程的优先级别,范围:1-10,默认为5,优先级越高,表示获取CPU机会越多

sleep(long millis)

可以指定毫秒数,使线程休眠,休眠结束后可以继续执行线程

yield()

暂停当前正在执行线程对象(以及放弃当前拥有的cpu资源),并执行其他线程;就绪后仍然可以抢占资源

join()

作用是:“等待该线程终止",join()后面的方法要等该线程执行完才会执行。

setDaemon(boolean on)

主线程的附庸,主线程执行完毕后不管守护线程有没有执行完,都会停止

wait()

释放锁,进入阻塞,需要notify()或者notifyAll()唤醒

wait(long timeout)

在超过指定的时间前,释放锁,进入等待队列

notify()

随机唤醒,通知一个线程,对应wait()

notifyAll()

唤醒、通知所有wait()的线程

四、生命周期

生命周期

描述

新建状态(NEW)

线程对象创建后,即进入了新建状态 :Thread t = new MyThread();

就绪状态(RUNNABLE)

调用线程对象的start()方法,线程进入有序状态

运行状态(RUNNING)

进入就绪状态后,CPU开始调度执行方法

阻塞状态(BLOCKED)

等待阻塞:wait();同步阻塞:synchronized;其他阻塞:sleep()、join()、I/O请求

线程死亡(DEAD)

执行完成或异常退出

五、线程安全

1、同步代码块

// 存在线程安全
public class TestDemo {
    public static void main(String[] args) throws Exception {
       RunnableDemo runnableDemo = new RunnableDemo();
       Thread t1 = new Thread(runnableDemo,"线程1");
       Thread t2 = new Thread(runnableDemo,"线程2");
       t1.start();
       t2.start();
    }
}

class RunnableDemo implements Runnable{
    private Integer index = 1;
    @Override
    public void run() {
        try {
            // 存在两个线程拿到index为1,同时进入判断,然后执行index--;
            if (index>0){
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName()+": RunnableDemo方法逻辑"+index--);
            }
        } catch (InterruptedException e) {

        }

    }
}
// 其中一直情况:
//线程1: RunnableDemo方法逻辑1
//线程1: RunnableDemo方法逻辑1
//加同步代码块后
public class TestDemo {
    public static void main(String[] args) throws Exception {
       RunnableDemo runnableDemo = new RunnableDemo();
       Thread t1 = new Thread(runnableDemo,"线程1");
       Thread t2 = new Thread(runnableDemo,"线程2");
       t1.start();
       t2.start();
    }
}

class RunnableDemo implements Runnable{
    private Integer index = 1;
    @Override
    public void run() {
        try {
            // 将同步锁加入到代码块上,括号里面上锁的对象(this)只要唯一即可 
            synchronized (this){
                if (index>0){
                    Thread.sleep(2000);
                    System.out.println(Thread.currentThread().getName()+": RunnableDemo方法逻辑"+index--);
                }
            }
        } catch (InterruptedException e) {
        }
    }
}
//线程1: RunnableDemo方法逻辑1

2、同步方法

public class TestDemo {
    public static void main(String[] args) throws Exception {
       RunnableDemo runnableDemo = new RunnableDemo();
       Thread t1 = new Thread(runnableDemo,"线程1");
       Thread t2 = new Thread(runnableDemo,"线程2");
       t1.start();
       t2.start();
    }
}

class RunnableDemo implements Runnable{
    private Integer index = 1;
    @Override
    public  void run() {
        try {
            sun();
        } catch (Exception e) {
        }
    }
    // 将同步锁加入到方法上面 
    public synchronized void sun() throws Exception {
        if (index>0){
            Thread.sleep(200);
            System.out.println(Thread.currentThread().getName()+": RunnableDemo方法逻辑"+index--);
        }
    }
}

3、锁机制Lock

lock()

获取锁,如果锁被占用,则等待

tryLock()

尝试获取锁,成功:true,失败:false,不阻塞

unlock

释放锁

public class TestDemo {
    public static void main(String[] args) throws Exception {
       RunnableDemo runnableDemo = new RunnableDemo();
       Thread t1 = new Thread(runnableDemo,"线程1");
       Thread t2 = new Thread(runnableDemo,"线程2");
       t1.start();
       t2.start();
    }
}

class RunnableDemo implements Runnable{
    private Integer index = 1;
    // ReentrantLock可重入锁,synchronized也是重入锁的一种
    private Lock rLock = new ReentrantLock();
    @Override
    public  void run() {
        rLock.lock();
        // 重复上锁,即重入锁
        rLock.lock();
        try {
            sun();
        } catch (Exception e) {
        }finally {
            // 阿巴 阿巴 阿巴
            rLock.unlock();
            rLock.unlock();
        }
    }
    public  void sun() throws Exception {
        if (index>0){
            Thread.sleep(200);
            System.out.println(Thread.currentThread().getName()+": RunnableDemo方法逻辑"+index--);
        }
    }
}

六、线程池

newFixedThreadPool

创建一个固定长度的线程池,当达到线程最大数量时,线程池的规模将不再变化

newCachedThreadPool

创建一个可缓存的线程池,如果当前线程池的规模超出处理需求,将回收空的线程;当需求增加时,会增加线程数量;线程池规模无限制。

newSingleThreadExecutor

创建一个单线程的Executor,确保任务对了,串行执行

newScheduledThreadPool

创建一个固定长度的线程池,而且以延迟或者定时的方式来执行

public class TestDemo {
    public static void main(String[] args) throws Exception {
        Object o = new Object();
        RunnableDemo runDemo1 = new RunnableDemo();
        RunnableDemo runDemo2 = new RunnableDemo();
        RunnableDemo runDemo3 = new RunnableDemo();
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2);
        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
        ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
        ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(2);

        System.out.println("----------------------newFixedThreadPool----------------------");
        Thread.sleep(1000);
        newFixedThreadPool.submit(runDemo1);
        newFixedThreadPool.submit(runDemo2);
        newFixedThreadPool.submit(runDemo3);
        Thread.sleep(1000);
        System.out.println("--------------------------------------------------------------");

        Thread.sleep(1000);

        System.out.println("----------------------newCachedThreadPool----------------------");

        newCachedThreadPool.submit(runDemo1);
        newCachedThreadPool.submit(runDemo2);
        newCachedThreadPool.submit(runDemo3);
        Thread.sleep(1000);
        System.out.println("--------------------------------------------------------------");

        System.out.println("----------------------newSingleThreadExecutor----------------------");
        Thread.sleep(1000);
        newSingleThreadExecutor.submit(runDemo1);
        newSingleThreadExecutor.submit(runDemo2);
        newSingleThreadExecutor.submit(runDemo3);
        Thread.sleep(1000);
        System.out.println("--------------------------------------------------------------");

        System.out.println("----------------------newScheduledThreadPool----------------------");
        Thread.sleep(1000);
        newScheduledThreadPool.schedule(runDemo1,10,TimeUnit.SECONDS);
        newScheduledThreadPool.schedule(runDemo2,10,TimeUnit.SECONDS);
        newScheduledThreadPool.schedule(runDemo3,10,TimeUnit.SECONDS);
    }
}

class RunnableDemo implements Runnable{
    @Override
    public  void run() {
        System.out.println(Thread.currentThread().getName()+": 方法逻辑");
    }
}
//----------------------newFixedThreadPool----------------------
//pool-1-thread-1: 方法逻辑
//pool-1-thread-2: 方法逻辑
//pool-1-thread-1: 方法逻辑
//--------------------------------------------------------------
//----------------------newCachedThreadPool----------------------
//pool-2-thread-1: 方法逻辑
//pool-2-thread-3: 方法逻辑
//pool-2-thread-2: 方法逻辑
//--------------------------------------------------------------
//----------------------newSingleThreadExecutor----------------------
//pool-3-thread-1: 方法逻辑
//pool-3-thread-1: 方法逻辑
//pool-3-thread-1: 方法逻辑
//--------------------------------------------------------------
//----------------------newScheduledThreadPool----------------------
//pool-4-thread-1: 方法逻辑
//pool-4-thread-2: 方法逻辑
//pool-4-thread-1: 方法逻辑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值