JAVA多线程浅析

什么是多线程

Java 给多线程编程提供了内置的支持。 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。

这里定义和线程相关的另一个术语 - 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。

多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。

如何使用

继承Thread类创建线程

 

/**
 * 多线程实现的第一种方法,继承Thread 
 *
 */

//1.自定义一个类,继承java.lang包下的Thread类
class MyThread extends Thread {
    //2.重写run方法
    public void run() {        
        //3.将要在线程中执行的代码编写在run方法中
        for(int i = 0; i < 1000; i++) {        
            System.out.println("monkey");
        }
    }
}

public class ThreadTest01 extends Thread {

    public static void main(String[] args) {
        //4.创建上面自定义类的对象
        //创建一个线程
        MyThread mt = new MyThread();        

        //5.调用start方法启动线程
        mt.start();                            

        //将循环的次数设置多一些,否则还没等到CPU切换就已经打印完成了
        for(int i = 0; i < 1000; i++) {
            System.out.println("1024");
        }
    }

}

实现Runnable接口创建线程

/**
 * 多线程实现的第二种方法,实现Runnable接口
 *
 */

// 1.自定义一个类实现java.lang包下的Runnable接口
class MyRunnable implements Runnable {

    // 2.重写run方法
    @Override
    public void run() {
        // 3.将要在线程中执行的代码编写在run方法中
        for (int i = 0; i < 1000; i++) {
            System.out.println("monkey");
        }
    }

}

public class ThreadTest02 {

    public static void main(String[] args) {
        // 4.创建上面自定义类的对象
        MyRunnable mr = new MyRunnable();

        // 5.创建Thread对象并将上面自定义类的对象作为参数传递给Thread的构造方法
        Thread t = new Thread(mr); 

        //6.调用start方法启动线程
        t.start();

        for (int i = 0; i < 1000; i++) {
            System.out.println("1024");
        }
    }

}

实现Callable接口创建线程

import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 多线程实现的第三种方法,实现Callable接口 优点: 可以获取返回值 可以抛出异常
 */

//1.定义一个类实现Callable<V>接口
class MyCallable implements Callable<Integer> {

    //睡眠时间
    private long second;

    //计算阶乘
    private int count;

    public MyCallable(int count, long second) {
        this.count = count;
        this.second = second;
    }

    // 2.重写call方法
    @Override
    public Integer call() throws Exception {
        // 3.将要执行的代码写在call方法中
        // 计算阶乘
        //让当前线程睡眠,单位是毫秒
        Thread.sleep(second);
        int sum = 1;

        if (count == 0) {
            sum = 0;
        } else {
            for (int i = 1; i <= count; i++) {
                sum *= i;
            }
        }

        // 打印线程名称
        System.out.println(Thread.currentThread().getName() + "-----sum=" + sum);

        return sum;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

}

public class ThreadTest03 {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //4.创建ExecutorService线程池
        ExecutorService exec = Executors.newCachedThreadPool();

        //5.创建存储Future对象的集合,用来存放ExecutorService的执行结果
        ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>();

        //6.开启2个线程,将返回的Future对象放入集合中
        for (int i = 0; i < 2; i++) {
            if (i == 0) {
                //计算5的阶乘,睡眠10秒
                results.add(exec.submit(new MyCallable(5, 10000)));
            } else {
                //计算3的阶乘,睡眠i秒
                results.add(exec.submit(new MyCallable(3, i)));
            }
        }


        for (Future<Integer> fs : results) {
            //7.判断线程是否执行结束,如果执行结束就将结果打印
            if (fs.isDone()) {
                System.out.println("计算结果:" + fs.get());
            } else {
                System.out.println(fs.toString() + "该线程还没有计算完毕,请耐心等待");
            }
        }

        //8.关闭线程池,不再接收新的线程,未执行完的线程不会被关闭
        exec.shutdown();
        System.out.println("main方法执行结束");
    }

}

三种实现方式的比较

  • 继承Thread
    • 优点:可以直接使用Thread类中的方法,代码简单
    • 缺点:继承Thread类之后就不能继承其他的类
  • 实现Runnable接口
    • 优点:即时自定义类已经有父类了也不受影响,因为可以实现多个接口
    • 缺点: 在run方法内部需要获取到当前线程的Thread对象后才能使用Thread中的方法
  • 实现Callable接口
    • 优点:可以获取返回值,可以抛出异常
    • 缺点:代码编写较为复杂
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章