Java创建线程实例详解

1.通过继承Thread类创建

具体步骤为:
1.继承Thread类,并重写run方法。run方法里面的逻辑就是线程要执行的逻辑。
2.创建子类的对象实例。
3.必须要使用对象实例的start方法启动该线程,不能直接使用run方法。

public class MyThread extends Thread {

    @Override
    public void run() {
        for(int i=0; i<50; i++) {
            String threadName = Thread.currentThread().getName();
            System.out.println("cur thread is: " + threadName + ", i is: " + i);
        }
    }

    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        thread1.setName("线程1");
        MyThread thread2 = new MyThread();
        thread2.setName("线程2");
        thread1.start();
        thread2.start();
    }
}

某次运行的结果

cur thread is: 线程1, i is: 0
cur thread is: 线程1, i is: 1
cur thread is: 线程1, i is: 2
cur thread is: 线程1, i is: 3
cur thread is: 线程1, i is: 4
cur thread is: 线程1, i is: 5
cur thread is: 线程1, i is: 6
cur thread is: 线程1, i is: 7
cur thread is: 线程1, i is: 8
cur thread is: 线程1, i is: 9
cur thread is: 线程1, i is: 10
cur thread is: 线程1, i is: 11
cur thread is: 线程1, i is: 12
cur thread is: 线程1, i is: 13
cur thread is: 线程1, i is: 14
cur thread is: 线程1, i is: 15
cur thread is: 线程1, i is: 16
cur thread is: 线程1, i is: 17
cur thread is: 线程1, i is: 18
cur thread is: 线程1, i is: 19
cur thread is: 线程1, i is: 20
cur thread is: 线程1, i is: 21
cur thread is: 线程1, i is: 22
cur thread is: 线程1, i is: 23
cur thread is: 线程1, i is: 24
cur thread is: 线程1, i is: 25
cur thread is: 线程1, i is: 26
cur thread is: 线程1, i is: 27
cur thread is: 线程1, i is: 28
cur thread is: 线程1, i is: 29
cur thread is: 线程2, i is: 0
cur thread is: 线程1, i is: 30
cur thread is: 线程2, i is: 1
cur thread is: 线程1, i is: 31
cur thread is: 线程2, i is: 2
cur thread is: 线程1, i is: 32
cur thread is: 线程2, i is: 3
cur thread is: 线程1, i is: 33
cur thread is: 线程2, i is: 4
cur thread is: 线程1, i is: 34
cur thread is: 线程2, i is: 5
cur thread is: 线程1, i is: 35
cur thread is: 线程2, i is: 6
cur thread is: 线程1, i is: 36
cur thread is: 线程2, i is: 7
cur thread is: 线程1, i is: 37
cur thread is: 线程2, i is: 8
cur thread is: 线程1, i is: 38
cur thread is: 线程2, i is: 9
cur thread is: 线程1, i is: 39
cur thread is: 线程2, i is: 10
cur thread is: 线程1, i is: 40
cur thread is: 线程2, i is: 11
....

使用继承Thread的方式创建线程,缺点就是因为java的单继承机制,使得该类无法再继承其他类。

2.通过Runnable接口创建

具体步骤为:
1.定义实现类实现Runnable接口,并实现run方法,run方法中的逻辑即为该线程的具体逻辑。
2.创建Runnable实现类的实例,并以该实例作为Thread的target参数创建Thread对象。
3.调用该Thread对象的start方法启动线程。

public class MyRunnable implements Runnable {

    @Override
    public void run() {
        for(int i=0; i<50; i++) {
            String threadName = Thread.currentThread().getName();
            System.out.println("cur thread is: " + threadName + ", i is: " + i);
        }
    }

    public static void main(String[] args) {
        MyRunnable obj = new MyRunnable();
        new Thread(obj, "线程1").start();
        new Thread(obj, "线程2").start();
    }
}

某次运行结果为:

cur thread is: 线程2, i is: 0
cur thread is: 线程1, i is: 0
cur thread is: 线程2, i is: 1
cur thread is: 线程1, i is: 1
cur thread is: 线程2, i is: 2
cur thread is: 线程1, i is: 2
cur thread is: 线程2, i is: 3
cur thread is: 线程1, i is: 3
cur thread is: 线程2, i is: 4
cur thread is: 线程1, i is: 4
cur thread is: 线程2, i is: 5
cur thread is: 线程1, i is: 5
cur thread is: 线程2, i is: 6
cur thread is: 线程2, i is: 7
...

3.Callable与Future创建

基本步骤为:
1.创建Callable接口实现类,实现run方法。注意Callable的源码为

@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

run方法中是后返回类型的。
2.创建Callable实现类的实例对象,并使用Future的实现类FutureTask类包装Callable实例对象。
3.使用FutureTask对象作为Thread对象的target创建并调用start方法启动线程。
4.可以使用FutureTask对象的get方法获取子线程结束执行以后的返回值。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * author: wanglei
 * create: 2022-08-18
 */
public class MyCallable implements Callable<Integer> {

    @Override
    public Integer call() {
        for(int i=0; i<50; i++) {
            String name = Thread.currentThread().getName();
            System.out.println("子线程" + name + "值为" + i);
        }
        return 50;
    }

    public static void main(String[] args) {
        MyCallable obj = new MyCallable();
        FutureTask<Integer> task = new FutureTask<>(obj);
        for(int j=0; j<50; j++) {
            System.out.println("主线程" + Thread.currentThread().getName() + "值为: " + j);
            if (j == 10) {
                new Thread(task, "有返回值的线程").start();
            }
        }
        try {
            System.out.println("子线程返回值: " + task.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

某次运行结果为

/home/mi/wanglei/soft/jdk1.8.0_251/bin/java -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:57127,suspend=y,server=n -javaagent:/home/mi/wanglei/soft/idea-IC-201.7223.91/plugins/java/lib/rt/debugger-agent.jar -Dfile.encoding=UTF-8 -classpath /home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/charsets.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/deploy.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/ext/cldrdata.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/ext/dnsns.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/ext/jaccess.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/ext/jfxrt.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/ext/localedata.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/ext/nashorn.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/ext/sunec.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/ext/sunjce_provider.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/ext/sunpkcs11.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/ext/zipfs.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/javaws.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/jce.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/jfr.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/jfxswt.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/jsse.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/management-agent.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/plugin.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/resources.jar:/home/mi/wanglei/soft/jdk1.8.0_251/jre/lib/rt.jar:/home/mi/wanglei/gitcode/mycoding/target/classes:/home/mi/wanglei/soft/idea-IC-201.7223.91/lib/idea_rt.jar bit.edu.leilei.service.MyCallable
Connected to the target VM, address: '127.0.0.1:57127', transport: 'socket'
主线程main值为: 0
主线程main值为: 1
主线程main值为: 2
主线程main值为: 3
主线程main值为: 4
主线程main值为: 5
主线程main值为: 6
主线程main值为: 7
主线程main值为: 8
主线程main值为: 9
主线程main值为: 10
主线程main值为: 11
主线程main值为: 12
主线程main值为: 13
主线程main值为: 14
主线程main值为: 15
主线程main值为: 16
主线程main值为: 17
主线程main值为: 18
主线程main值为: 19
主线程main值为: 20
主线程main值为: 21
主线程main值为: 22
主线程main值为: 23
主线程main值为: 24
主线程main值为: 25
主线程main值为: 26
主线程main值为: 27
主线程main值为: 28
主线程main值为: 29
主线程main值为: 30
子线程有返回值的线程值为0
主线程main值为: 31
子线程有返回值的线程值为1
主线程main值为: 32
子线程有返回值的线程值为2
主线程main值为: 33
子线程有返回值的线程值为3
主线程main值为: 34
子线程有返回值的线程值为4
主线程main值为: 35
子线程有返回值的线程值为5
主线程main值为: 36
主线程main值为: 37
主线程main值为: 38
主线程main值为: 39
主线程main值为: 40
主线程main值为: 41
主线程main值为: 42
主线程main值为: 43
主线程main值为: 44
主线程main值为: 45
主线程main值为: 46
主线程main值为: 47
主线程main值为: 48
主线程main值为: 49
子线程有返回值的线程值为6
子线程有返回值的线程值为7
子线程有返回值的线程值为8
子线程有返回值的线程值为9
子线程有返回值的线程值为10
子线程有返回值的线程值为11
子线程有返回值的线程值为12
子线程有返回值的线程值为13
子线程有返回值的线程值为14
子线程有返回值的线程值为15
子线程有返回值的线程值为16
子线程有返回值的线程值为17
子线程有返回值的线程值为18
子线程有返回值的线程值为19
子线程有返回值的线程值为20
子线程有返回值的线程值为21
子线程有返回值的线程值为22
子线程有返回值的线程值为23
子线程有返回值的线程值为24
子线程有返回值的线程值为25
子线程有返回值的线程值为26
子线程有返回值的线程值为27
子线程有返回值的线程值为28
子线程有返回值的线程值为29
子线程有返回值的线程值为30
子线程有返回值的线程值为31
子线程有返回值的线程值为32
子线程有返回值的线程值为33
子线程有返回值的线程值为34
子线程有返回值的线程值为35
子线程有返回值的线程值为36
子线程有返回值的线程值为37
子线程有返回值的线程值为38
子线程有返回值的线程值为39
子线程有返回值的线程值为40
子线程有返回值的线程值为41
子线程有返回值的线程值为42
子线程有返回值的线程值为43
子线程有返回值的线程值为44
子线程有返回值的线程值为45
子线程有返回值的线程值为46
子线程有返回值的线程值为47
子线程有返回值的线程值为48
子线程有返回值的线程值为49
子线程返回值: 50
Disconnected from the target VM, address: '127.0.0.1:57127', transport: 'socket'

Process finished with exit code 0

4.使用线程池创建

实际工作场景中,使用线程池创建线程较为常见,具体可以参考如下。

java线程池小结

5.以上方式对比

5.1 Thread方式

直接继承Thread类的方式,实现简单方便,但是因为单继承问题,无法再继承其他类。

5.2 Runnable方式

解决了单继承问题,但是run方法返回的void类型,无法获取对应的返回值。同时,run方法也无法抛出异常。

5.3 Callable方式

1.Callable需要重写call方法,并且call方法可以返回值,同时还可以处理异常。
2.Callable可以返回一个异步的Future对象。通过Future对象可以跟踪线程执行情况,并且可以通过get方法获取线程结果。

5.4 线程池方式

实际项目中,一般都是使用线程池进行线程管理。其优点有
1.提升代码性能。因为创建线程是一个比较重的操作,使用线程池可以减少线程创建销毁等的性能开销。
2.可以方便实现定时任务,控制并发数,单线程等功能。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java回调函数是一种在Java中实现事件驱动编程的重要机制。回调函数允许您将一个函数作为参数传递给其他函数,并在需要时调用它。回调函数是Java中实现事件驱动编程的重要工具,可以用于处理各种事件,如用户交互、定时器触发、数据读取等。 在Java中,回调函数通常使用接口来实现。接口是一种定义了一组方法的抽象类型,这些方法在实现时可以由任何类来实现。回调函数通常通过实现接口中的方法来实现,并在需要时调用这些方法。 下面是一个简单的回调函数示例: ```java interface Callback { void call(); } public class MyClass { private Callback callback; public void doSomething(Callback callback) { this.callback = callback; // 做一些事情 if (callback != null) { callback.call(); } } } ``` 在上面的示例中,`Callback` 接口定义了一个名为 `call()` 的方法,用于在适当的时候被调用。`MyClass` 类将 `Callback` 接口的实现作为参数传递给 `doSomething()` 方法,并在完成后调用 `call()` 方法。 当您需要使用回调函数时,您可以将一个实现了回调接口的类的实例传递给需要使用回调的方法。该方法将在适当的时候调用回调方法,并将结果传递给该实例的方法或属性。这样,您就可以根据需要执行其他操作或处理回调结果。 使用回调函数可以简化代码并提高代码的可维护性,因为它允许您将复杂的事件处理逻辑封装在单独的方法中,并使用回调函数将其与主程序分离。这使得代码更加清晰和易于理解,并且可以在需要时轻松地扩展和修改代码。 需要注意的是,使用回调函数时需要注意线程安全问题。由于回调函数通常是在其他线程中执行的,因此需要确保在调用回调方法时正确地同步和保护数据,以避免出现并发问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值