Java 多线程概念

来源:互联网 发布:淘宝上买的药是正品吗 编辑:程序博客网 时间:2024/06/06 03:14

概念

1.一个对象就是一个线程,多个对象就是多线程,一块资源就是进程,多块资源就是多进程,多个对象抢一块资源就是并发,多个对象抢多块资源就是并行
2.一块资源就是一个或多个共享变量,多个对象共享一块资源就必须要同步锁,否则会变成多个对象每一个对象都有一块资源
3.javaw
4.主线程的入口是main,子线程的入口是run,主线程是特殊的线程,与其他子线程同时进行,不需要和其他子线程抢夺CPU资源,除非遇到线程控制方法。
start开启一条子线程,不影响当前线程运行。
join开启一条子线程后,将这条子线程加入当前线程,必须先执行完这条子线程,当前线程才能继续执行
yeild出让资源给同优先级的子线程,不影响主线程
5.开启的子线程默认是前台线程(不会因为当前线程退出而退出),setDaemon设置为后台线程(当前线程退出,后台线程必须退出),设置后台线程必须在start之前
6.线程的生命周期:
新建:new
就绪:start();一个线程只能开启一次,准备抢资源
运行:抢到资源,开始执行代码块(可能刚执行完一条代码,又被别的线程抢回去了)
阻塞:线程暂停(sleep、wait、join、suspend、IO阻塞…)
死亡:run方法执行完毕,线程退出

线程创建的三种方法

//1.新建一个类继承Thread,重写run方法,创建该类的对象,调用start方法public class Test{    public static void main(String[] args){        Person per1 = new Person();        Person per2 = new Person();        per1.start();        per2.start();    }}class Person extends Thread{    public void run()    }}//简写形式new Thread() {    public void run() {        System.out.println("我是子线程");    }}.start();//2.新建一个类实现runnable接口,重写run方法,创建runnable对象,使用runnable对象来创建Thread,调用start方法public class Test {    public static void main(String[] args) {        Person per = new Person();        Thread th1 = new Thread(per);        Thread th2 = new Thread(per);        th1.start();        th2.start();    }}class Person implements Runnable{    public void run() {    }}//简写形式new Thread(new Runnable() {     public void run() {        System.out.println("我是子线程");    }}).start();//3.新建一个类实现Callback接口,创建callback实例,用callback对象来创建futuretask实例,用futuretask对象来创建thread实例,调用thread.start方法,如果需要获取结果,可以用futuretask对象调用get方法获取线程返回,但会阻塞当前线程

同步锁

1.把访问到的共享变量全部括起来
2.括起来之后要使用同一把锁(obj、this、类类型)

线程通信(wait、notify方法)

1.必须放在同步锁中
2.调用者必须是锁
3.调用wait进入休眠状态,并释放锁

线程池概念

线程池就是管理线程,是线程的集合,线程池中的线程能够并发执行,提供了两个主要主要方法:

1.execute();开始执行任务
2.shutdown();线程池关闭,线程消失不维护
3.shutdownnow();立即关闭线程池,sleep无法终结

线程池创建

//1.缓冲线程池;第一次可以开启任意个线程,第二次开启如果有空闲的线程,就会去重用它ExecutorService ctp = Executors.newCachedThreadPool();ctp.execute(new Runnable() {    @Override    public void run() {    }});//2.固定线程:不管开启多少个任务,线程池只会用3条线程来执行,执行完后复用原来3条线程ExecutorService ftp = Executors.newFixedThreadPool(3);ftp.execute(new Runnable() {    @Override    public void run() {    }});//3.单线程:只开启一条线程,相当于固定线程的参数1ExecutorService ste = Executors.newSingleThreadExecutor();ste.execute(new Runnable() {    @Override    public void run() {    }});//4.定时器:ScheduledExecutorService stp =Executors.newScheduledThreadPool(1);System.out.println("延迟任务5秒后开启");stp.schedule(new Runnable() {    @Override    // 延迟任务    public void run() {        System.out.println("任务开启");    }}, 5000, TimeUnit.MILLISECONDS);//关闭定时器stp.shutdown();ScheduledExecutorService stp1 = Executors.newScheduledThreadPool(1);stp1.scheduleAtFixedRate(new Runnable() {    int i = 5;    @Override    // 周期任务定时器    public void run() {        if (i == 0) {            System.out.println("没了");            stp1.shutdown();        } else {            System.out.println("离世界末日还有" + (i--) + "秒");        }    }//6s后开启任务,每隔1s执行一次任务,ms单位}, 6000, 1000, TimeUnit.MILLISECONDS);//5.Timer类也有定时器功能Timer timer = new Timer();timer.schedule(new TimerTask() {    int i = 5;    @Override    public void run() {        System.out.println("1s执行1次," + i + "s后关闭定时器");        if ((--i) == 0) {            System.out.println("关闭定时器");            timer.cancel();        }    }}, 3000, 1000);//定时器必须是单个线程

小练习

1.龟兔赛跑2.生产者消费者(几条线程、共享变量)