多线程快速巩固学习

一、基本概念

进程

程序在运行时的一个实例,在任何时间点上,只能有一个进程在运行,由于进程切换速度快,人类无法察觉,宏观并行,微观串行。

线程

轻量级的进程,一个进程中可以包含多个线程,每个线程可以完成不同的工作,交替执行。
CPU调度时的基本单位

二、线程的创建和使用

2.1、线程的创建
a)、继承Thread
/**
*	1、创建一个类继承Thread类
*	2、覆盖Thread的run方法
*	3、创建该类的对象
*	4、调用start()方法
**/
class MyThread extends Thread{
    public void run() {
        for (int i = 0; i < 100; i++) {
            if(i%2==0) System.out.println(i);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        t1.start();
    }
}

附:Thread类中的部分方法使用
* start():启动一个线程中的run()方法
 * run(): 覆盖Thread中的run方法,所要执行的操作
 * currentThread(): 静态方法,返回执行当前代码的线程
 * getName():获取线程的名字
 * setName():设置当前线程的名字
 * yield():释放cpu的执行权
 * join():在线程a中调用线程b的join,a会进入阻塞状态,直至b线程执行完毕,a线程才会被释放
 * sleep():设置线程睡眠时间
 * isAlive():判断线程是否存活
 *
 * 线程优先级
 * MIN_PRIORITY:1
 * NORM_PRIORITY:5
 * MAX_PRIORITY:10
 * 线程优先级
 * getpriority():获取
 * setpriority():设置
卖票问题
/**
 * @program: javademo
 * @description: 卖票问题(会出现重复票号)
 * @author: Tang
 * @create: 2019-10-08 15:05
 **/
class Window extends Thread{
    private static int ticket = 100;

    @Override
    public void run() {
        while (true){
            if(ticket > 0){
                System.out.println(getName()+"成功出售"+ticket+"号");
                ticket--;
            }else break;
        }
    }
}
public class TestWindow {
    public static void main(String[] args) {
        Window w1 = new Window();
        Window w2 = new Window();
        Window w3 = new Window();

        w1.start();
        w2.start();
        w3.start();
    }
}
b)、实现Runnable接口
class MineThread implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if(i%2==0) System.out.println(i);
        }
    }
}
public class TestRunable  {
    public static void main(String[] args) {
        MineThread mineThread = new MineThread();

        Thread t1 = new Thread(mineThread);
        t1.start();
    }
}
两种方式的比较

1.实现Runnable接口不存在继承Thread类的局限性(java单继承)。

2.实现的方式更适合多个线程共享数据的情况

三、线程的生命周期

在这里插入图片描述

四、线程的同步

同步代码块
语法:

synchronized(临界资源){
    //只有得到临界资源锁标记的线程,方可执行
    //原子操作
}
//当同步代码块执行完毕后,会释放掉该临界资源的所标记
//其他线程竞争该锁标记

同步方法
语法:

访问权限修饰符 synchronized 返回值类型 方法名(参数表)抛出的异常{
    //当前对象(this)作为锁标记
    //当多个线程对同一个对象调用该方法时,只能有一个线程得到锁标记
    //其他线程在当前对象的锁池中 等待锁标记
}

五、线程的通信

涉及方法

wait():让当前线程进入阻塞状态,并释放同步监视器。

notify():执行此方法会唤醒被wait的线程,此时如果有多个wait的线程,则会唤醒优先级高的线程。

notifyAll():唤醒所有被wait()的线程

/**
 * @description: 两个线程交替打印1~100
 **/
class TestRunnablee implements Runnable{

    private int start = 1;
    @Override
    public void run() {
        while (true){
            synchronized(this){
                this.notify();
                if(start<=100){
                    
                    System.out.println(Thread.currentThread().getName()+":"+start);
                    start++;

                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }else break;
            }

        }
    }
}
public class TestPlus {
    public static void main(String[] args) {
        TestRunnablee testRunnablee = new TestRunnablee();

        // 创建线程对象
        Thread t1 = new Thread(testRunnablee);
        Thread t2 = new Thread(testRunnablee);

        t1.setName("线程一");
        t2.setName("线程二");

        t1.start();
        t2.start();
    }
}
面试题

sleep() 和wait()的区别?

相同:二者都会使线程进入阻塞状态

不同:sleep不会释放锁,会自动打开阻塞。

​ wait()需要手动打开阻塞状态

经典案例:生产者消费者
/**
 * @description: 生产者消费者案例
 **/
class Phone{
    private int phoneNum = 0;

    public synchronized void add(){
        if(phoneNum <100){
            phoneNum++;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"生产了"+phoneNum+"部手机");
            notify();
        }else {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

    }
    public synchronized void reduce(){
        if(phoneNum>0){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"购买了"+phoneNum+"部手机");
            phoneNum--;
            notify();
        }else {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}
//  生产者
class Producer implements Runnable{
    private Phone phone;

    public Producer(Phone phone) {
        this.phone = phone;
    }

    @Override
    public void run() {
        while (true){
            phone.add();
        }

    }
}
//  消费者
class Consumer implements Runnable{
    private Phone phone;

    public Consumer(Phone phone) {
        this.phone = phone;
    }

    @Override
    public void run() {
        while (true) {
            phone.reduce();
        }
    }
}
public class ProducerConsumer {
    public static void main(String[] args) {
        Phone phone = new Phone();
        Producer producer = new Producer(phone);
        Consumer consumer = new Consumer(phone);

        Thread p = new Thread(producer);
        p.setName("生产者");
        Thread c = new Thread(consumer);
        c.setName("消费者");

        p.start();
        c.start();

    }
}

六、JDK5.0新增线程的创建方式

实现Callable接口
class ICallable implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        int num = 0;

        for (int i = 0; i < 100; i++) {
            if(i % 2 == 0){
                System.out.println(i);
                num+=i;
            }
        }

        return num;
    }
}
public class TestCallable {
    public static void main(String[] args) {

        ICallable iCallable = new ICallable();

        FutureTask<Integer> futureTask = new FutureTask<Integer>(iCallable);
        new Thread(futureTask).start();

        try {
            Integer value = futureTask.get();
            System.out.println(value+"========================");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }
}
线程池
class Runnable1 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if(i%2 == 0) System.out.println(i);
        }
    }
}
public class ThreadPoll {
    public static void main(String[] args) {
        //  创建一个容量为10的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //  启动该线程
        executorService.execute(new Runnable1());
        //  归还线程
        executorService.shutdown();

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值