多线程

一、多线程介绍

1、Java中创建线程的方法3种:Thread、Runnable、Callable

  • 继承Thread类 (Thread类本身就是实现Runnable接口的)
  • 实现Runnable接口
  • 实现Callable接口

2、继承Thread类

①通过继承Thread类,重写run方法实现多线程
/**
 * 通过继承Thread类,重写run方法实现多线程
 */
@Slf4j
public class TestThread1 extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 200; i++)
            log.info("子线程输出:" + Thread.currentThread().getName() + "-" + i);
    }

    public static void main(String[] args) {
        TestThread1 test1 = new TestThread1();  //新开第1个线程
        test1.start(); //start方法启动线程

        TestThread1 test2 = new TestThread1();  //新开第2个线程
        test2.start(); //start方法启动线程

        for (int i = 0; i < 200; i++) {
            log.info("主线程输出:" + Thread.currentThread().getName() + "-" + i);
        }
    }
}

②通过匿名内部类,重写run方法实现多线程
/**
 * 通过匿名内部类,重写run方法实现多线程
 */
@Slf4j
public class TestThread2 {

    public static void main(String[] args) {

        Thread thread = new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    if (i % 2 == 1) {
                        //打印线程名,线程名是从0开始的
                        log.info("子线程输出:" + Thread.currentThread().getName() + "-" + i);
                    }
                }
            }
        };
        thread.start();

        Thread thread1 = new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    if (i % 2 == 1) {
                        //打印线程名,线程名是从0开始的
                        log.info("子线程输出:" + Thread.currentThread().getName() + "-" + i);
                    }
                }
            }
        };
        thread1.start();

        for (int i = 0; i < 100; i++) {
            if (i % 2 == 1) {
                //打印线程名,线程名是从0开始的
                log.info("主线程输出:" + Thread.currentThread().getName() + "-" + i);
            }
        }
    }
}

3、实现Runnable接口

/**
 * 通过Runnable接口,重写run方法,实现多线程
 */
@Slf4j
public class TestThread3 implements Runnable {
    
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            log.info("子线程输出:" + Thread.currentThread().getName() + "-" + "看书++++++++");
        }
    }

    public static void main(String[] args) {
        //创建runnable接口的实现类对象
        TestThread3 testThread3 = new TestThread3();
        //创建线程对象,通过线程对象来开启我们的线程,代理
        Thread thread1 = new Thread(testThread3);  //新开第1个线程
        thread1.start();

        Thread thread2 = new Thread(testThread3);  //新开第2个线程
        thread2.start();

        for (int i = 0; i < 200; i++) {
            log.info("主线程输出:" + Thread.currentThread().getName() + "-" + "写字++++++++");
        }
    }
}

4、实现Callable接口

/**
 * 通过Callable接口,重写call方法,实现多线程
 */
@Slf4j
public class TestThread4 implements Callable<Integer> {

    @Override
    public Integer call() {
        int count = 0;
        for (int i = 0; i < 200; i++) {
            if (i % 2 == 0) {
                count++;
                log.info("子线程输出:" + Thread.currentThread().getName() + "-" + count);
            }
        }
        return count;
    }

    public static void main(String[] args) throws Exception {

        TestThread4 testThread4 = new TestThread4();  //新开1个线程
        FutureTask<Integer> futureTask = new FutureTask<>(testThread4);
        new Thread(futureTask).start();  //开启线程

        for (int i = 0; i < 200; i++) {
            log.info("主线程输出:" + Thread.currentThread().getName() + "-" + i);
        }

        log.info("主线程输出:" + Thread.currentThread().getName() + "-" + futureTask.get());

    }
}


二、多线程和线程池的区别

  • 线程池是在程序运行开始,创建好的n个线程,并且这n个线程挂起等待任务的到来;而多线程是在任务到来得时候进行创建,然后执行任务。
  • 线程池中的线程执行完之后不会回收线程,会继续将线程放在等待队列中;多线程程序在每次任务完成之后会回收该线程。
  • 由于线程池中线程是创建好的,所以在效率上相对于多线程会高很多。
  • 线程池在高并发的情况下有着较好的性能,不容易挂掉;多线程在创建线程数较多的情况下,很容易挂掉。
posted @ 2023-02-23 14:24  南翔技校毕业后  阅读(24)  评论(0)    收藏  举报