Loading

[Java并发]Thread

Thread源码

构造方法

Thread()
Allocates a new Thread object.

Thread(Runnable target)
Allocates a new Thread object.

Thread(Runnable target, String name)
Allocates a new Thread object.

Thread(String name)
Allocates a new Thread object.

Thread(ThreadGroup group, Runnable target)
Allocates a new Thread object.

Thread(ThreadGroup group, Runnable target, String name)
Allocates a new Thread object so that it has target as its run object, has the specified name as its name, and belongs to the thread group referred to by group.

Thread(ThreadGroup group, Runnable target, String name, long stackSize)
Allocates a new Thread object so that it has target as its run object, has the specified name as its name, and belongs to the thread group referred to by group, and has the specified stack size.

Thread(ThreadGroup group, String name)
Allocates a new Thread object.

Java 开启线程的四种方式

实现runnable接口

这个方法有一个很大的缺点就是重写的run方法是没有返回值的,如果想要返回值,需要使用下面的方法

public class RunnableImpl implements Runnable {

    /*
    * 创建步骤如下:
    * 1,定义Runnable接口的实现类,并且实现run方法,这个方法同样是线程执行体
    * 2,创建Runnable实现类的实例,并以此实例对象作为Thread的target来创建Thread类,这个新创建的Thread对象才是真正的线程对象,即开启了新的线程
    * 3,调用线程对象的start()方法来开启该线程
    *
    * 调用示例:
    * //开启10个线程
    * for (int i = 0; i < 10; i++) {
    *     Thread thread = new Thread(new RunnableImpl());
    *     thread.start();
    * }
    * */

    /**
     * 实现Runnable接口的run方法,这个方法称为线程执行体
     * */
    @Override
    public void run() {
        doSomething();
    }

    /**
     * 需要处理的任务
     * */
    private void doSomething(){
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "执行" + i);
        }
    }
}

实现callable接口

实现callable接口的类的实例对象不能直接当做线程执行体传递给thread,

而是需要先用futuretask包裹,从实现callable转为实现runnable,

再把task传递给thread构造线程。

这种方法可以获得方法执行的返回值,call() 方法的返回值类型取决于你在实现 Callable 接口时指定的泛型参数类型,返回值被task接收,

还可以抛出异常,

public class CallableImpl implements Callable<String> {

    /*
     * 创建步骤如下:
     * 1,定义实现Callable<V>接口的实现类,实现call方法,这个方法是线程执行体
     * 2,创建Callable<V>实现类的实例,借助FutureTask得到线程执行的返回值
     * 3,将FutureTask的实例,作为Thread的target来创建Thread类
     * 4,调用start方法,开启线程
     *
     * 调用示例:
     * Callable<String> tc = new CallableImpl();
     * FutureTask<String> task = new FutureTask<>(tc);
     * new Thread(task).start();
     * try {
     *     System.out.println(task.get());
     * } catch (InterruptedException | ExecutionException e) {
     *     e.printStackTrace();
     * }
     *
     * 说明:
     * 1.与使用Runnable相比, Callable功能更强大些
     * 2.实现的call()方法相比run()方法,可以返回值
     * 3.方法可以抛出异常
     * 4.支持泛型的返回值
     * 5.需要借助FutureTask类,比如获取返回结果
     * Future接口可以对具体Runnable、Callable任务的执行结果进行取消、查询是否完成、获取结果等。
     * FutureTask是Futrue接口的唯一的实现类
     * FutureTask 同时实现了Runnable, Future接口。它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值
     *
     * */

    private int ticket = 5;

    @Override
    public String call() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println(doSomething());
        }

        return "出票任务完成";
    }

    public String doSomething() {
        String result = "";
        if (this.ticket > 0) {
            result = "出票成功,ticket=" + this.ticket--;
        } else {
            result = "出票失败,ticket=" + this.ticket;
        }
        return result;
    }
}

继承thread类

public class ExtendThread extends Thread {

    /*
    * 创建步骤如下:
    * 1,定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务。因此把run方法称为线程执行体。
    * 2,创建Thread子类的实例,即创建线程对象。本实例中是new一个ExtendThread,即可创建线程对象,也就是开启了一个线程
    * 3,调用线程对象的start()方法来启动该线程。
    *
    * 调用示例:
    * //循环10次即开启10个线程
    * for (int i = 0; i < 10; i++) {
    *     ExtendThread extendThread = new ExtendThread();
    *     extendThread.start();
    * }
    * */

    /**
     * 重写Thread类的run(),这个方法称为线程执行体
     * */
    @Override
    public void run() {
        doSomething();
    }

    /**
     * 需要处理的任务
     * */
    public void doSomething(){
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "执行" + i);
        }
    }
}

创建线程池

public class RunnableImpl implements Runnable {

    /*
     * 创建步骤如下:
     * 1,定义Runnable接口的实现类,或者定义(继承Runnable接口的类)的实现类,并且实现run方法,这个方法是线程执行体
     * 2,创建一个自定义线程个数的线程池
     * 3,实例化Runnable接口的实现类
     * 4,将3步的实例,作为线程池实例的execute方法的command参数,开启线程
     * 5,关闭线程池
     *
     * 调用示例:
     * ExecutorService pool = Executors.newFixedThreadPool(2);
     * RunnableImpl runnableImpl1 = new RunnableImpl("AA");
     * RunnableImpl runnableImpl2 = new RunnableImpl("BB");
     * pool.execute(runnableImpl1);
     * pool.execute(runnableImpl2);
     * pool.shutdown();
     *
     * 说明:
     * 示例中创建的是2个线程的线程池
     * execute方法是开启线程方法,实参要求是实现Runnable的类。所以,继承Thread类的子类也可以以线程池的方式开启线程,因为thread类实现了runnable接口
     *
     * */

    String name;
    public RunnableImpl(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        doSomething();
    }

    /**
     * 需要处理的任务
     * */
    private void doSomething() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "执行" + i + ",name=" + this.name);
        }
    }
}

匿名内部类

public class Anonymous {

    /*
    * 创建步骤如下:
    * 匿名内部类本质上也是一个类实现了Runnable接口,重写了run方法,只不过这个类没有名字,直接作为参数传入Thread类
    *
    * 调用示例:
    * //开启10个线程
    * for (int i = 0; i < 10; i++) {
    *     Anonymous anonymous =new Anonymous();
    *     anonymous.myRun();
    * }
    *
    * */

    public void myRun(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                doSomething();
            }
        }).start();
    }

    /**
     * 需要处理的任务
     * */
    private void doSomething(){
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "执行" + i);
        }
    }
}

在Java中,A线程调用B线程做某些工作,对于B的结果,A线程只想等待特定的时间而非一直等待,应该怎么做?

在Java中,你可以使用Thread.join()方法来等待一个线程执行完成,但是这会一直等待直到被等待的线程执行完成为止。如果你希望在等待一段特定的时间后不再等待,你可以结合使用Thread.join()TimeUnit类。以下是一个示例:

public class Main {
    public static void main(String[] args) {
        // 创建B线程并启动
        Thread bThread = new Thread(() -> {
            // B线程执行一些工作
            // ...

            // 假设B线程执行完成后设置了一些结果
            System.out.println("B线程执行完成");
        });

        bThread.start();

        // A线程等待B线程执行一段时间
        try {
            long timeoutMillis = 5000; // 设置等待时间为5秒
            bThread.join(timeoutMillis);

            if (bThread.isAlive()) {
                // 如果B线程在超时时间内仍然没有执行完成
                System.out.println("B线程还未执行完成,超时退出");
            } else {
                // 如果B线程在超时时间内执行完成
                System.out.println("A线程继续执行,B线程执行完成");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在上面的例子中,bThread.join(timeoutMillis)会等待B线程最多执行timeoutMillis毫秒的时间。如果B线程在超时时间内执行完成,那么A线程会继续执行,否则A线程会在超时后不再等待B线程而继续执行自己的逻辑。

posted @   Duancf  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示