JAVA多线程

JAVA多线程

线程的创建的方式:

一:继承Thread类

由于JAVA里一个子类只能继承一个父类,所以继承Thread后的线程类无法拥有更多的功能,是最简单的创建线程的方法,学习阶段尝试线程感觉很方便

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

        //3.new一个新线程对象
        Thread t = new MyThread();
        //4.调用start方法启动线程(实际执行的还是run方法)
        t.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("11111111111");
        }
    }
}


/**
    1.定义一个线程类继承Thread类
 */
class MyThread extends Thread {
    /**
        2.重写run方法,里面是定义线程以后要干啥
     */
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("============");
        }

    }
}

二:实现Runnable接口

定义Runnable接口的实现类,只是实现了接口,可以继续继承类和实现接口,扩展性强,Runnable的实现类创建的对象只是任务对象,需要交给Thread进行包装,Thread类才是真正的线程对象

public class ThreadDemo2 {
    public static void main(String[] args) {
        //3.创建一个任务对象
        Runnable target = new MyRunnable();
        //4.把任务对象交给Thread处理
        Thread t = new Thread(target);
        //5.启动线程
        t.start();

        //主线程随便写点东西
        for (int i = 0; i < 10; i++) {
            System.out.println("主线程执行输出:" + i);
        }
    }
}

/**
 * 1.定义一个线程任务类,实现Runnable接口
 */
class MyRunnable implements Runnable {

    /*
        2.重写run方法,定义线程的执行的任务
     */
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("子线程执行输出:" + i);
        }
    }
}

//lambda表达式简化
/*

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println("子线程2执行输出:" + i);
                }
            }
        }).start();


        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println("子线程3执行输出:" + i);
            }

        }).start();
        */

三:实现Callable接口,用FutureTask创建新线程

将Callable的实现类包装到FutureTask里,再将FutureTask类作为任务对象包装到Thread类,可以调用FutureTask类的get()方法得到线程执行的返回值

(泛型里面是子线程执行结束后的返回值)

public class ThreadDemo3 {
    public static void main(String[] args) {
        //3.创建Callable 任务对象
        Callable<String> call = new MyCallable(100);

        //4.把Callable任务对象 交给FutureTask对象
        //FutureTask对象的作用1:是Runnable的对象(实现了Runnable接口),可以交给Thread了
        //FutureTask对象的作用2:可以在线程执行完毕之后通过调用其get方法得到线程执行完毕后的结果

        FutureTask<String>f1 = new FutureTask<>(call);
        //5.交给线程处理
        Thread t1  = new Thread(f1);
        //6.启动线程
        t1.start();

        Callable<String> call2 = new MyCallable(200);
        FutureTask<String>f2 = new FutureTask<>(call2);
        Thread t2  = new Thread(f2);
        t2.start();
        /**
        get方法是FutureTask的方法
         */
        try {
            String rs = f1.get();
            System.out.println("线程1"+rs);
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            String rs2 = f2.get();
            System.out.println("线程2"+rs2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


/**
 * 1.定义一个任务类  实现Callable接口    应该声明线程任务执行完毕后的结果的数据类型
 */
class MyCallable implements Callable<String>{
    private int n;

    public MyCallable(int n) {
        this.n = n;
    }

    public MyCallable() {
    }

    /*
    重写call方法(任务方法)
     */
    @Override
    public String call() throws Exception {
        int sum = 0;
        for (int i = 1; i <=n ; i++) {
            sum+=i;
        }
        return "执行的结果是:"+sum;
    }
}

利用线程池创建新线程

一:Runnable的实现类在线程池里用execute执行

public class ThreadPoolDemo1 {
    public static void main(String[] args) {
        /*
        public ThreadPoolExecutor(int corePoolSize,  指定线程池的线程数量(核心线程)
                              int maximumPoolSize,  指定线程池可支持的最大线程数
                              long keepAliveTime,  指定临时线程的最大存活时间
                              TimeUnit unit,  指定存活世间的单位(秒、分、时、天)
                              BlockingQueue<Runnable> workQueue,  指定任务队列 workQueue
                              ThreadFactory threadFactory,  指定用哪个线程工厂创建线程 :threadFactory
                              RejectedExecutionHandler handler  指定线程忙,任务满的时候,新任务来了的处理方法)
         */
        //1.创建线程池对象
        ExecutorService pool = new ThreadPoolExecutor(3, 5, 6, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());//丢弃任务并抛出异常(听说一般用这个)
        //ThreadPoolExecutor.CallerRunsPolicy  由主线程负责调用任务的run方法从而绕过线程池直接执行
        //ThreadPoolExecutor.DiscardPolicy   丢弃任务,但是不抛出异常
        //ThreadPoolExecutor.DiscardOldestPolicy   抛弃队列中等待最久的任务,然后把当前任务加入队列中

        //2.给任务线程池处理
        Runnable target = new MyRunnable();
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);

    }
}

二:Callable的实现类用submit执行

public class ThreadPoolDemo2 {
    public static void main(String[] args) throws Exception {
        /*
        public ThreadPoolExecutor(int corePoolSize,  指定线程池的线程数量(核心线程)
                              int maximumPoolSize,  指定线程池可支持的最大线程数
                              long keepAliveTime,  指定临时线程的最大存活时间
                              TimeUnit unit,  指定存活世间的单位(秒、分、时、天)
                              BlockingQueue<Runnable> workQueue,  指定任务队列 workQueue
                              ThreadFactory threadFactory,  指定用哪个线程工厂创建线程 :threadFactory
                              RejectedExecutionHandler handler  指定线程忙,任务满的时候,新任务来了的处理方法)
         */
        //1.创建线程池对象
        ExecutorService pool = new ThreadPoolExecutor(3, 5, 6, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());//丢弃任务并抛出异常(听说一般用这个)
        //ThreadPoolExecutor.CallerRunsPolicy  由主线程负责调用任务的run方法从而绕过线程池直接执行
        //ThreadPoolExecutor.DiscardPolicy   丢弃任务,但是不抛出异常
        //ThreadPoolExecutor.DiscardOldestPolicy   抛弃队列中等待最久的任务,然后把当前任务加入队列中

        //2.给任务线程池处理
        Future<String> f1 = pool.submit(new MyCallable(100));
        Future<String> f2 = pool.submit(new MyCallable(200));
        Future<String> f3 = pool.submit(new MyCallable(300));
        Future<String> f4 = pool.submit(new MyCallable(400));
        Future<String> f5 = pool.submit(new MyCallable(500));

        System.out.println(f1.get());
        System.out.println(f2.get());
        System.out.println(f3.get());
        System.out.println(f4.get());
        System.out.println(f5.get());
    }
}

三:使用Executors的工具方法直接得到一个线程池对象

public class ThreadPoolDemo3 {
    public static void main(String[] args) {
        //1.创建固定线程数据的线程池
        //允许请求的任务队列长度是Integer.MAX_VALUE
        ExecutorService pool = Executors.newFixedThreadPool(3);//创建固定线程数量的线程池,有线程异常,就补充一个新的
        //ExecutorService pool = Executors.newSingleThreadExecutor();// z

        //创建线程数量最大上限是Integer.MAX_VALUE
        //ExecutorService pool = Executors.newCachedThreadPool();
        //ExecutorService pool = Executors.newScheduledThreadPool();

        pool.execute(new MyRunnable());
    }
}

Executors的工具方法底层还是采用ThreadPoolExecutor方法创建线程池

线程安全

使用synchronized关键字给线程加锁,一般使用对应的对象作为锁

静态方法可以使用类名.class作为锁

线程通信

使用notify唤醒等待的线程

使用wait将当前线程休眠

public class Phone {

    //实现线程间通信,默认认为手机当前处于等待来电提醒
    private boolean flag = false;

    public void run() {
        //a.负责来电提醒的线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    synchronized (Phone.this) {
                        if (!flag) {
                            //代表要来电话提醒了

                            try {
                                System.out.println("有新电话呼入,可以接听");
                                flag = true;
                                Thread.sleep(1000);
                                Phone.this.notify();
                                Phone.this.wait();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }).start();
        //b.接电话线程,正式接听

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //不断地接听电话
                    while (true) {
                        synchronized (Phone.this) {
                            if (flag) {
                                //可以接听电话了
                                System.out.println("电话已接通,这两人正在聊天");
                                Thread.sleep(1000);
                                flag = false;
                                //唤醒别人,等待自己
                                Phone.this.notify();
                                Phone.this.wait();
                            } else {
                                Phone.this.notify();
                                Phone.this.wait();
                            }
                        }
                    }


                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public static void main(String[] args) {
        //1.创建一部手机对象
        Phone phone = new Phone();
        phone.run();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值