多线程学习笔记

多线程简介

什么是线程?

线程是进程中的一个执行场景,一个进程可以启动多个线程

使用多线程可以提高CPU的使用率,不是提高执行速度。

线程和线程之间共享堆内存和方法区,栈内存是独立的,每个线程有自己独立的栈

进程包含多个线程。

多线程的缺点

    • 设计复杂
      多线程中共享堆内存和方法区,因此里面的一些数据是可以共享的,在设计时要确保数据的准确性
    • 资源消耗增多
      栈内存是不共享的,如果启用多个线程的话会占用更多的内存

多线程创建的三种方式之继承Thread类

package ThreadTest;

/**
 * 多线程练习继承Thread
 */
public class ThreadTest01 {
    public static void main(String[] args) {
            new MyThread().start();
            new Thread(){
                @Override
                public void run() {
                    for (int i = 0; i < 1000; i++) {
                        System.out.println("线程1");
                    }
                }
            }.start();
    }
}

class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("线程0");
        }
    }
}

多线程创建的三种方式之实现Runnable接口

package ThreadTest;

public class ThreadTest02 {
    public static void main(String[] args) {
        MyRunnable mr = new MyRunnable();
        new Thread(mr).start();

        new Thread(new Runnable(){
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("线程1");
                }
            }
        }){
        }.start();
    }
}

class MyRunnable implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("线程0");
        }
    }
}

多线程创建的三种方式之实现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方法执行结束");
    }
}

匿名内部类的方式创建多线程

package ThreadTest;

import java.util.concurrent.*;

public class 匿名内部测试方法 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
             new Thread(){
                 @Override
                 public void run() {
                     for (int i = 0; i < 100; i++) {
                         System.out.println("Thread的线程");
                     }
                 }
             }.start();

             new Thread(
                     new Runnable() {
                         @Override
                         public void run() {
                             for (int i = 0; i < 100; i++) {
                                 System.out.println("实现Runnable接口的线程");
                             }
                         }
                     }
             ){

             }.start();

        ExecutorService es = Executors.newCachedThreadPool();  //创建线程池
        Future<Integer> submit = es.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return 1024;
            }
        });
        System.out.println(submit.get());
    }
}

给线程命名和获取线程名

package ThreadTest;

import java.util.concurrent.*;

public class 匿名内部测试方法 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        new Thread("Thread线程") {
            @Override
            public void run() {
                System.out.println(getName());
            }
        }.start();

        new Thread(
                new Runnable() {
                    @Override
                    public void run() {
                        Thread.currentThread().setName("Runnable线程");
                        System.out.println(Thread.currentThread().getName());
                    }
                }
        ) {

        }.start();

        ExecutorService es = Executors.newCachedThreadPool();  //创建线程池
        Future<Integer> submit = es.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                Thread.currentThread().setName("Callable线程");
                System.out.println(Thread.currentThread().getName());
                return 1024;
            }
        });
        System.out.println(submit.get());
    }
}

线程睡眠

Thread中的sleep方法可以使当前线程睡眠,线程睡眠后,里面的任务不会执行,待睡眠时间过后会自动苏醒,从而继续执行任务。

Thread中有两个重载的sleep方法
sleep(long millis),指定睡眠毫秒数
sleep(long millis, int nanos),第一个参数是毫秒,第二个参数是纳秒。

package ThreadTest;

/**
 * 使用Thread中的Sleep方法令线程睡眠
 */
public class ThreadSleepTest01 {
    public static void main(String[] args) {
//           new Thread(){
//               @Override
//               public void run() {
//                   for (int i = 0; i < 10; i++) {
//                       try {
//                           Thread.sleep(1000);
//                       } catch (InterruptedException e) {
//                           e.printStackTrace();
//                       }
//                       System.out.println("睡眠线程!");
//                   }
//               }
//           }.start();
//
//           new Thread(){
//               @Override
//               public void run() {
//                   for (int i = 0; i < 10; i++) {
//                       try {
//                           Thread.sleep(1000);
//                       } catch (InterruptedException e) {
//                           e.printStackTrace();
//                       }
//                       System.out.println("1024");
//                   }
//               }
//           }.start();

        new Thread() {
            @Override
            public void run() {
                for (int i = 10; i > 0; i--) {
                    System.out.println(i);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }
}

唤醒正在睡眠的线程

package ThreadTest;

/**
 * 使用Thread中的Sleep方法令线程睡眠
 */
public class ThreadSleepTest01 {
    public static void main(String[] args) {

        Thread td = new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(10000000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                for (int i = 0; i < 10; i++) {
                    System.out.println("sleep");
                }
            }
        };
        td.start();
        td.interrupt();
    }
}

这里会打印出InterruptedException异常

 

 

原文地址:https://www.cnblogs.com/xiaowangtongxue/p/10890138.html