Java中多线程详解(1)创建线程的方式

165 阅读4分钟

一、多线程介绍

1.什么是多线程

        在学习多线程前,我们先简单了解一下什么是线程;线程可能大家平常比较少见,但是相信大家对进程这个词都不陌生,所谓进程可以理解为一个进行中程序,最常见的一个例子就是平常有程序卡死了,我们就会打开任务管理器去结束掉这个进程,如下图:

        而线程其实和进程大同小异,进程是操作系统中的一个独立的模块,而线程就是进程中的一个独立的模块,一个操作系统中执行多个程序就是多进程,一个进程执行多个线程就是多线程。

2.为什么要用多线程

        很简单,提高效率,举个例子,你如果要洗衣服,你肯定会先让洗衣机放水。然后在放水时把脏衣服收拾出来放到洗衣机里,然后放洗衣液进去,之后在等洗衣机洗衣服的同时去把衣架整理出来,而不是等洗衣机水放完了才放洗衣液,然后放衣服,等衣服洗完了才去找衣架,虽然只有一个人,但是同时为了洗衣服同时做好几件事情,这样效率就可以大大提高;在计算机中,一个CPU就可以看成一个人,洗衣服可以看成一个进程,放水、收拾衣服、找衣架就相当与是多个线程,利用好多线程就可以在主线程执行任务的同时可以执行其他任务,而不需要等待。

二、在Java中如何创建线程

1.继承Thread类

创建步骤

  (1)创建多线程类继承Thread;

(2)重写Thread中的run方法,run中用来添加线程的方法;

(3)在主函数中创建实例;

(4)用创建的实例调用run方法;

下面是一个例子

public class ThreadTest extends Thread{
    public static void main(String[] args) {
        ThreadTest t1 =new ThreadTest();
        ThreadTest t2 =new ThreadTest();
        ThreadTest t3 =new ThreadTest();
        double start = System.currentTimeMillis() ;
        t1.run();
        t2.run();
        t3.run();
        double end = System.currentTimeMillis() ;
        System.out.println("time is : " + (end - start));
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+":正在执行!"+i);
        }
    }
}

可以看到在这个例子中我添加了一个计算程序运行时间的方法,这个方法验证了上面所说到多线程高效率,注意看下图中的线程数和时间。

可以明显的看出来,执行一个线程所需要的时间和执行三个线程所需要的时间是一样的,而不是和线程数量成正比。

2.实现Runable接口

创建步骤

(1)创建类实现Runnable接口

(2)重写Runnable接口中的run方法,run中用来添加线程的方法。

(3)创建Runable实例,创建Thread实例建立线程对象,将Runnable实例对象作为实际参数传递给Thread对象

(4)用Thread的实例对象调用start方法

class RunableTest implements Runnable {
    public static void main(String[] args) {
        Runnable runn = new RunableTest();
        Thread thread = new Thread(runn);
        Thread thread2 = new Thread(runn);
        thread.start();
        thread2.start();
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("线程执行!"+i);
        }
    }
}

看到这里,相信不少人和我之前一样有一个疑问,Thread和Runable有什么区别呢,为什么要实现Runable接口呢?

Thread和Runable本质上只有一个区别,那就是一个是类一个是接口,Runable没有单继承的限制(其实Thread也是继承了Runable接口的)

3通过Callable和Future实现多线程

创建步骤

(1)创建线程类继承Callable,重写call()方法,这个call()用来添加该线程的方法,和Runable不同的是它有返回值。
(2)创建Callable实现类的实例对象,创建FutureTask的实例对象,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
(3)使用FutureTask对象作为Thread对象的参数创建并启动新线程。
(4)调用FutureTask对象的get()方法来获得线程执行结束后的返回值

class CallableTest implements Callable {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CallableTest callableTest = new CallableTest();
        FutureTask futureTask = new FutureTask(callableTest);
        new Thread(futureTask).start();
        Object result = futureTask.get();
        System.out.println(result);
    }
    @Override
    public String call() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println("线程执行!" + i);
        }
        return "运行结束";
    }
//运行结果
线程执行!0
线程执行!1
线程执行!2
线程执行!3
线程执行!4
线程执行!5
线程执行!6
线程执行!7
线程执行!8
线程执行!9
运行结束