JavaSE进阶知识(三)

本文深入探讨Java中的多线程实现方式,包括直接继承Thread、实现Runnable和Callable接口,并讲解线程生命周期、线程安全问题及解决方案。同时,文章介绍了反射机制的应用,如动态创建对象、访问属性和方法,以及注解的使用和意义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多线程

进程是一个应用程序(1个进程是一个软件),线程是一个进程中的执行场景/执行单元,一个进程可以启动多个线程。

进程可以看做是现实生活当中的公司,线程可以看做是公司当中的某个员工。

进程A和进程B的内存独立不共享

线程A和线程B堆内存和方法区内存共享,但是栈内存独立,一个线程一个栈。假设启动10个线程,会有10个栈空间,每个栈和每个栈之间,
互不干扰,各自执行各自的,这就是多线程并发。

火车站,可以看做是一个进程,火车站中的每一个售票窗口可以看做是一个线程,我在窗口1购票,你可以在窗口2购票,你不需要等我,我也不需要等你,所以多线程并发可以提高效率。

使用了多线程机制之后,main方法结束,是不是有可能程序也不会结束,main方法结束只是主线程结束了,主栈空了,其它的栈(线程)可能还在压栈弹栈。

 java中实现线程有三种方式

第一种方式:编写一个类,直接继承java.lang.Thread,重写run方法

public class Test01 {
    public static void main(String[] args) {
        MyThread m = new MyThread();
        // 不会启动线程,不会分配新的分支栈(这种方式是单线程)
        // m.run();

        // 启动线程
        // start()方法的作用是在jvm中开辟一个新的栈空间,只要栈空间开出来了,start方法就结束了,线程就启动成功了
        // 启动的线程会自动调用run()方法,并且run方法在分支栈的底部,main方法在主栈的底部,run方法和main方法是平级的,
        m.start();
        // 下面的代码还是运行在主线程中
        for (int i = 0; i < 1000; i++) {
            System.out.println("主线程" + i);
        }
    }
}

class MyThread extends Thread {
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("分支线程" + i);
        }
    }
}

第二种方式:编写一个类,实现java.lang.Runnable接口,实现run方法

建议使用接口方式,因为实现这个接口还可以去继承其他类,第一种方式继承Thread类之后就不能继承其他类了

public class Test02 {
    public static void main(String[] args) {
/*        // 创建一个可运行的对象
        MyRunnable m = new MyRunnable();
        // 将可运行的对象封装成一个线程
        Thread t = new Thread(m);*/

        // 合并代码
        Thread t = new Thread(new MyRunnable());
        // 启动线程
        t.start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("主线程" + i);
        }
    }
}

class MyRunnable implements Runnable {
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("分支线程" + i);
        }
    }
}

 第二种方式:编写一个类,实现java.util.concurrent.Callable接口

优点:可以获取线程返回的结果

缺点:在获取线程结果时,会导致当前线程阻塞

public class Test10 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyCallable m = new MyCallable();
        FutureTask task = new FutureTask(m);

        Thread t1 = new Thread(task);
        t1.start();
        // 获取call方法的返回值
        // get()方法会导致main线程阻塞
        Object o = task.get();
        System.out.println(o);  // 5秒后才输出300
    }
}

class MyCallable implements Callable {

    @Override
    public Object call() throws Exception {
        Thread.sleep(5000);
        return 300;
    }
}

线程生命周期

 获取和修改线程的名字,休眠线程

public class Test03 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyRunnable2());
        System.out.println(t1.getName()); // Thread-0
        t1.setName("t1");
        System.out.println(t1.getName()); // t1

        Thread t2 = new Thread(new MyRunnable2());
        System.out.println(t2.getName());  // Thread-1

        // 获取当前线程对象
        Thread currentThread = Thread.currentThread();
        System.out.println(currentThread.getName());  // main

        try {
            // 当前线程休眠
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("hello"); // hello会在5秒后才输出

    }
}

class MyRunnable2 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("分支线程" + i);
            System.out.println(Thread.currentThread().getName());
        }
    }
}

 打断线程的休眠

public class Test04 {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable3());
        t.start();
        // 希望5秒之后t线程醒来
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 终端t线程的睡眠,这种终断睡眠依靠java的异常机制
        t.interrupt();
    }
}

class MyRunnable3 implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "start");
        try {
            Thread.sleep(1000 * 60 * 60);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "end");
    }
}

合理终止线程的睡眠

打一个布尔标记

public class Test05 {
    public static void main(String[] args) {
        MyRunnable4 r = new MyRunnable4();
        Thread t = new Thread(r);
        t.start();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // t.stop()  不建议使用,会直接杀死进程,导致数据未保存
        r.run = false;
    }
}

class MyRunnable4 implements Runnable {
    boolean run = true;

    public void run() {
        for (int i = 0; i < 10; i++) {
            if (run) {
                System.out.println(Thread.currentThread
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风里有诗句哈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值