线程的实现方法

242 阅读3分钟

我正在参与掘金创作者训练营第6期,点击了解活动详情

在并发的场景中实现线程是其中必须的,只有实现了多线程才可以进行一系列的操作。

创建线程

实现 Runnable 接口

创建类实现 Runnable 接口或者创建一个 Runnable 类的实例,并重写 run 方法。我的理解是该类相当于是一个任务,run 方法中是要执行的业务内容。所以要执行该任务必须将其放在 Thread 中并调用 start 方法才行。

   public void example1(){
        Runnable rn = new Runnable() {
            @Override
            public void run() {
                System.out.println(" Runable 方法实现线程");
            }
        };

       Thread th1 = new Thread(rn)
       th1.start()
    }

继承 Thread 类

创建类继承 Thread 类,然后创建该类的实例。继承类必须重写 run() 方法。然后调用start 方法才能执行。可以看到

public class ExtendsThread extends Thread {
    @Override
    public void run() {
        System.out.println('用Thread类实现线程');
    }
}

线程池创建线程

static class DefaultThreadFactory implements ThreadFactory {
    DefaultThreadFactory() {
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
        Thread.currentThread().getThreadGroup();
        namePrefix = "pool-" +poolNumber.getAndIncrement() +
            "-thread-";
    }

    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r,
                    namePrefix + threadNumber.getAndIncrement(),

0);
        if (t.isDaemon()) t.setDaemon(false);
        if (t.getPriority() != Thread.NORM_PRIORITY)
            t.setPriority(Thread.NORM_PRIORITY);
        return t;
    }
}

从上面线程池的源代码上可看大,线程池其实就是个线程工厂。其中创建线程的本质其实还是通过 new Thread() 创建线程的。其中增加了创建线程是的一些默认设置,如线程的名字、是否守护线程和线程优先级等。

有返回值的 Callable 创建线程

class CallableThread implements Callable<String>{
    @Override
    public String call() throws Exception{
        return "Hello"
    }
}

// 创建线程池
ExecutorService service = Executors.newFixedThreadPool(10);
Future<String> future = service.submit(new CallableThread());

Runnable 创建的线程是无返回值的,而 Callable 接口是带有返回值的。从以上源代码可以看出,CallableThread 其实也是一个任务,需要通过 submit方法将任务放在线程池中,并由线程池创建线程。

总结

个人认为:一个线程的创建其实就是 Thread 类, run() 方法其实就是线程中要执行的内容,然后通过 start 方法启动并创建该线程。通过实现 Runnable 接口的创建出来的类应该是一个可执行的线程任务内容,真正最要还是要放在线程里然后通过 start 方法启动该线程去执行该任务。

所以 start() 方法其实就是创建一个线程出来,一个线程只能一个 start() 方法,重写的 run() 方法里其实放的就是所需要执行的任务。run() 要被执行只有通过 start() 方法去启动线程然后才会调用 run() 方法。

通过实现 Runnable 接口方式创建的线程要比继承 Thread 类实现线程要好。

  • Runnable 只有 run 方法,这样任务和线程 Thread 类 解耦。Runnable 负责定义要执行的内容,Thread 类负责线程启动和属性设置等内容,权责分明。
  • Runnable 方法可以直接将任务传给线程池,而如果使用 thread ,每次执行任务都需要新建一个独立的线程,太浪费性能开销
  • Java 不支持双继承,一旦继承了 Thread 类型,就会限制后续的扩展,扩展性低。