Java学习_20220626

多线程详解

Process和Thread

进程是执行程序的一次执行过程,是系统资源分配的单位。一个线程包括若干个线程(CPU调度和执行的单位)

程序(静态)-->进程-->线程(如main函数(用户线程)和gc函数(守护线程))

1.Thread方法

创建方式:继承Thread类,重写run()方法,调用start方法。

public class Thread_test extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 30; i++) {
            System.out.println("我在读书==="+i);
        }
    }
    public static void main(String[] args) {
        Thread_test thread_test = new Thread_test();
        //thread_test.run();//先调用run方法里面的方法体
        thread_test.start();//交叉执行,并行
        for (int i = 0; i < 30; i++) {
            System.out.println("今天是个好天气==="+i);
        }
    }
}

总结:注意,线程开启不一定立即执行,由cpu调度执行。

2. Runnable

实现Runnable接口,实现run()方法,编写线程执行体,创建线程对象,丢人runnable接口实现类,调用start()方法

public class Runnable_test implements Runnable{
    @Override
    public void run() { //run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我再执行线程==="+i);
        }
    }
    public static void main(String[] args) {
        Runnable_test runnable_test = new Runnable_test();
        //创建线程对象,通过线程对象来开启线程,代理的方式
        new Thread(runnable_test).start();
        for (int i = 0; i < 50; i++) {
            System.out.println("-----for------"+i);
        }
    }
}

Thread也实现了Runnable接口 ,Java单继承,推荐使用Runnable接口,方便同一个对象被多个线程使用。

多个线程操作同一个资源的情况下,线程不安全,数据紊乱

3. Callable接口

(1)实现Callable接口,需要返回值类型,

(2)重写call方法,需要抛出异常,

(3)创建目标对象

(4)创建执行服务:ExecutorService ser = ExecutorService .newFixedThreadPool(1);

(5)提交执行:Future<Boolean> result1 = ser.submit(t1);

(6)获取结果:boolean r1 =result1.get();

(7)关闭服务:ser.shutdownNow();

public class TestCallable implements Callable<Boolean>{
    @Override
    public Boolean call() {}
}

Callable 的好处:1.可以定义返回值,2.可以抛出异常。

4.静态代理模式

真实对象(目标对象)和代理对象都要实现同一个接口;

代理对象要代理真实角色(传入真实对象)

好处:

代理对象可以做很多真实对象做不了的事情。

真实对象只专注做自己的事情。

5.Lambda表达式

函数式接口:接口中只包含唯一一个抽象方法,可通过Lambda表达式来创建该接口的对象。(如Runnable中只有一个run抽象方法)

public class TestLambda1 { //实现接口的方式,较为复杂
    public static void main(String[] args) {
        Ilove ilove = new Mylove();//接口new实现类
        ilove.love("z");  //I love -> z
    }
}
interface Ilove{
    void love(String s);
}
class Mylove implements Ilove{
    @Override
    public void love(String s) {
        System.out.println("I love -> "+s);
    }
}
public class TestLambda1 {
    //静态内部类
    static class Youlove implements Ilove{
        @Override
        public void love(String s) {
            System.out.println("You love -> "+s);
        }
    }
    public static void main(String[] args) {
        Ilove youlove = new Youlove();
        youlove.love("A"); //You love -> A
    }
}
interface Ilove{//定义一个函数式接口
    void love(String s);
}
public class TestLambda1 {
    public static void main(String[] args) {
        //成员内部类
        class Shelove implements Ilove{
            @Override
            public void love(String s) {
                System.out.println("She love -> "+s);
            }
        }
        Shelove shelove = new Shelove();
        shelove.love("B"); //She love -> B
    }
}
interface Ilove{//定义一个函数式接口
    void love(String s);
}
public class TestLambda1 {
    public static void main(String[] args) {
        //匿名内部类
        Ilove helove = new Ilove() {
            @Override
            public void love(String s) {
                System.out.println("He LOVE -> "+s);
            }
        };
        helove.love("C"); //He LOVE -> C
    }
}
interface Ilove{//定义一个函数式接口
    void love(String s);
}
//Lambda表达式
Ilove itlove =s -> System.out.println("it LOVE -> " + s);
itlove.love("D");
//总结:
/*
lambda表达式只能有一行代码的情况下才能简化为一行,两行及以上的情况用代码块{}包裹。
使用前提接口必须为函数式接口(只有一个抽象方法)
多个参数也可以同时去掉参数类型,但必须加上括号
*/

6.线程状态

(1)线程停止

建议线程正常停止——>利用次数,不建议死循环;

建议使用标志位——>设置一个标志位;

不要使用stop或者destroy等过时或者JDK不建议使用的方法

public class ThreadStop_test implements Runnable{
    private boolean flag = true;//设置一个标志位
    @Override
    public void run() {
        int i = 0;
        while (flag){
            System.out.println("run.....Thread "+i++);
        }
    }
    public  void stop(){ //设置一个公开的方法停止线程,转换标志位
        this.flag = false;
    }
    public static void main(String[] args) {
        ThreadStop_test threadStop_test = new ThreadStop_test();
        new Thread(threadStop_test).start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("main"+i);
            if(i == 900){
                threadStop_test.stop(); //调用stop方法,让线程停止
                System.out.println("线程该停止了");
            }
        }
    }
}

(2)线程休眠

模拟网络延时:放大问题的发生性。(网络购票)

模拟倒计时

public class ThreadSleep_test {
    public static void main(String[] args) throws InterruptedException {
        new ThreadSleep_test().Down();
    }
    public void Down() throws InterruptedException {
        int num = 10;
        while(true){
            Thread.sleep(1000);
            System.out.println(num--);
            if(num<=0){
                break;
            }
        }
    }
}

打印当前时间

public static void main(String[] args) {
    //打印当前系统时间
    Date startDate = new Date(System.currentTimeMillis());//获取系统当前时间
    while (true){
        try {
            Thread.sleep(1000);
            //在循环体中重新获取一遍,可得到最新值
            startDate = new Date(System.currentTimeMillis());             
            System.out.println(new SimpleDateFormat("HH:mm:ss").format(startDate));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

(3)线程礼让

礼让线程,让当前正在执行的线程暂停,但不阻塞。将线程从运行状态转为就绪状态,该线程将再次和其他线程一起争取CPU资源,让cpu调度,所以礼让不一定成功。

Thread.yield();

获取当前线程的名字:Thread.currentThread().getName();

(4)合并线程Join(插队)

public class ThreadJoin_test implements Runnable{
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 1; i <= 100; i++) {
            System.out.println("线程在执行。。。"+i);
        }
    }
    public static void main(String[] args) throws InterruptedException {
        ThreadJoin_test threadJoin_test = new ThreadJoin_test();
        Thread thread = new Thread(threadJoin_test);
        thread.start();
        for (int i = 1; i <= 500; i++) {
            if(i==10){
                thread.join();//在主线程执行的过程中加入run方法中的方法体
            }
            System.out.println(Thread.currentThread().getName()+i);
        }
    }
}

(5)线程状态

thread.getState();

if ( state == Thread.State.TERMINATED )   // 判断线程是否终止

线程进入死亡状态,就不能再次启动。

(6)线程优先级

获取优先级:getPriority()

设置优先级:setPriority(int xxx)

(7)守护进程(daemon )

线程分为用户线程和守护线程、虚拟机必须确保用户线程执行完毕,但不用等待守护线程执行完毕。

线程变成守护线程:thread.setDaemon(true);//默认是false,表示用户线程,正常的线程都是用户线程。

posted @ 2022-06-26 17:51  浑浑噩噩一只小迷七  阅读(21)  评论(0)    收藏  举报