多线程(Thread)

一、实现多线程

多线程是为了同步完成多项任务,提高资源使用率提高系统使用率。

1、继承Thread类

void run() 在线程开启后,此方法将被调用执行,run()封装了被线程执行的代码
void start() 启动线程,Java虚拟机会调用run方法()、即由JVM调用此线程的run()方法
public class MultiThreaded extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("继承thread  " + i);
        }
    }

    public static void main(String[] args) {
        MultiThreaded multiThreaded = new MultiThreaded();
        MultiThreaded multiThreaded1 = new MultiThreaded();
        multiThreaded.start();
        multiThreaded1.start();
    }
}

2、实现Runnable接口

Thread(Runnable target) 分配一个新的Thread对象
Thread(Runnable target, String name) 分配一个新的Thread对象
public class RunnableThread implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + i);
        }
    }

    public static void main(String[] args) {
        RunnableThread run = new RunnableThread();

        //创建Thread类的对象,把RunnableThread对象作为构造方法的参数
        Thread is = new Thread(run, "is");
        Thread lunatic = new Thread(run, "lunatic");
        //启动线程
        is.start();
        lunatic.start();
    }
}

3、实现Callable接口

V call() 计算结果,如果无法计算结果,则抛出一个异常
FutureTask(Callable callable) 创建一个 FutureTask,一旦运行就执行给定的 Callable
V get() 如有必要,等待计算完成,然后获取其结果
public class CallableThread implements Callable {
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i < 100; i++) {
            sum += i;
        }
        //返回值就表示线程运行完毕之后的结果
        return sum;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //线程开启之后需要执行里面的call方法
        CallableThread call = new CallableThread();
        //可以获取线程执行完毕之后的结果.也可以作为参数传递给Thread对象
        FutureTask task = new FutureTask<>(call);
        //创建线程对象
        Thread thread = new Thread(task);
        //开启线程
        thread.start();
        Integer str = task.get();
        System.out.println("str = " + str);
    }
}

4、对比

实现 好处     坏处
实现Runnable、Callable接口 扩展性强,实现该接口的同时还可以继承其他的类 编程相对复杂,不能直接使用Thread类中的方法
继承Thread 编程比较简单,可以直接使用Thread类中的方法 可以扩展性较差,不能再继承其他的类

5、线程调度

分时调度模型 所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片
抢占式调度模型 优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些

线程优先级:默认优先级是5;设置优先级在1~10之间。

6、线程同步

同步代码块
public class RunnableThread implements Runnable {
    private int tickets = 100;
    private Object obj = new Object();
    @Override
    public void run() {
        while (true) {
            synchronized (obj) { // 对可能有安全问题的代码加锁,多个线程必须使用同一把锁
                //t1进来后,就会把这段代码给锁起来
                if (tickets > 0) {
                    try {
                        Thread.sleep(100);
                        //t1休息100毫秒
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                    tickets--; //tickets = 99;
                }
            }
            //t1出来了,这段代码的锁就被释放了
        }
    }

    public static void main(String[] args) {
        RunnableThread run = new RunnableThread();

        //创建Thread类的对象,把RunnableThread对象作为构造方法的参数
        Thread is = new Thread(run, "is");
        Thread lunatic = new Thread(run, "lunatic");
        //启动线程
        is.start();
        lunatic.start();
    }
}
好处 解决了多线程数据安全问题
坏处 当线程有多个,每个线程都会去判断同步上的锁,造成资源耗费严重,降低程序运行效率
 同步方法
public class TbRunnable implements Runnable{
    private static int ticketCount = 100;

    @Override
    public void run() {
        while(true){
            if("is".equals(Thread.currentThread().getName())){
                //同步方法
                boolean result = synchronizedMethod();
                if(result){
                    break;
                }
            }

            if("lunatic".equals(Thread.currentThread().getName())){
                //同步代码块
                synchronized (TbRunnable.class){
                    if(ticketCount == 0){
                        break;
                    }else{
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        ticketCount--;
                        System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + ticketCount + "张票");
                    }
                }
            }

        }
    }
    private static synchronized boolean synchronizedMethod() {
        if(ticketCount == 0){
            return true;
        }else{
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ticketCount--;
            System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + ticketCount + "张票");
            return false;
        }
    }

    public static void main(String[] args) {
        TbRunnable tb = new TbRunnable();
        Thread t1 = new Thread(tb);
        Thread t2 = new Thread(tb);

        t1.setName("is");
        t1.setName("lunatic");

        t1.start();
        t2.start();
    }
}
Lock锁:unlock(释放锁)和lock(获得锁)
public class Ticket implements Runnable {
    //票的数量
    private int ticket = 100;
    private Object obj = new Object();
    private ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            //synchronized (obj){//多个线程必须使用同一把锁.
            try {
                lock.lock();
                if (ticket <= 0) {

                    //卖完了
                    break;
                } else {
                    Thread.sleep(100);
                    ticket--;
                    System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + ticket + "张票");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
            // }
        }
    }

    public static void main(String[] args) {
        Ticket tk = new Ticket();
        Thread t1 = new Thread(tk);
        Thread t2 = new Thread(tk);
        Thread t3 = new Thread(tk);

        t1.setName("ttt1");
        t2.setName("ttt2");
        t3.setName("ttt3");

        t1.start();
        t2.start();
        t3.start();
    }
}

8、线程池

存放线程的容器

Executors线程池
public class MyThreadPoolDemo {
    public static void main(String[] args) throws InterruptedException {

        //1,创建一个默认的线程池对象.池子中默认是空的.默认最多可以容纳int类型的最大值.
        ExecutorService executorService = Executors.newCachedThreadPool();
        //Executors --- 可以帮助我们创建线程池对象
        //ExecutorService --- 可以帮助我们控制线程池

        executorService.submit(()->{
            System.out.println(Thread.currentThread().getName() + "在执行了");
        });

        Thread.sleep(2000);

        executorService.submit(()->{
            System.out.println(Thread.currentThread().getName() + "在执行了");
        });

        executorService.shutdown();
    }
}
ThreadPoolExecutor线程池
corePoolSize 核心线程的最大值,不能小于0
maximumPoolSize  最大线程数,不能小于等于0,maximumPoolSize >= corePoolSize
keepAliveTime  空闲线程最大存活时间,不能小于0
unit 时间单位
workQueue 任务队列,不能为null
threadFactory 创建线程工厂,不能为null    
handler 任务的拒绝策略,不能为null
public class MyThreadPoolDemo3 {
//    参数一:核心线程数量
//    参数二:最大线程数
//    参数三:空闲线程最大存活时间
//    参数四:时间单位
//    参数五:任务队列
//    参数六:创建线程工厂
//    参数七:任务的拒绝策略
    public static void main(String[] args) {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(2,5,2, TimeUnit.SECONDS,new ArrayBlockingQueue<>(10), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
        pool.submit(new RunnableThread());
        pool.submit(new RunnableThread());

        pool.shutdown();
    }
}

你可能感兴趣的:(java,jvm,开发语言)