简单了解在Java中的线程,以及如何创建并使用

本文介绍了Java线程的基础概念,包括线程与进程的关系、Thread类中start与run方法的区别、线程的六种状态及其转换方式。此外还详细阐述了在Java中创建线程的五种常见方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

简单了解在Java中的线程,以及如何创建并使用。其包括线程与进程的关系、在Java的Thread类中start与run方法的区别、在Java中线程的6种状态和转换方式、在Java中创建线程并使用的方式。

一、基本理解

1.什么是线程?

线程是进程中的一条执行路径,也是CPU的基本调度单位。一个进程至少要有一个线程(主线程),也可以有多个线程(可以创建子线程)。

2.线程与进程的区别

(1)进程是操作系统资源分配的基本单位,而线程是CPU的基本调度单位。
(2)一个运行中的应用至少有一个进程。
(3)一个进程至少要有一个线程(主线程),也可以有多个线程(可以创建子线程)。

3.在Java的Thread类中,start与run方法的区别

(1)start方法是启动一个新的线程的方法;
(2)run方法是在当前线程中执行的方法;
(3)当调用start方法时,会创建一个新的线程,并在新的线程中执行run方法;
(4)而直接调用run方法,会在当前线程中执行run方法,而不会创建新的线程;

4.Java中线程的6种状态(详情见源码:java/lang/Thread.java#state)

/**
 * A thread state.  A thread can be in one of the following states:
 * <ul>
 * <li>{@link #NEW}<br>
 *     A thread that has not yet started is in this state.
 *     </li>
 * <li>{@link #RUNNABLE}<br>
 *     A thread executing in the Java virtual machine is in this state.
 *     </li>
 * <li>{@link #BLOCKED}<br>
 *     A thread that is blocked waiting for a monitor lock
 *     is in this state.
 *     </li>
 * <li>{@link #WAITING}<br>
 *     A thread that is waiting indefinitely for another thread to
 *     perform a particular action is in this state.
 *     </li>
 * <li>{@link #TIMED_WAITING}<br>
 *     A thread that is waiting for another thread to perform an action
 *     for up to a specified waiting time is in this state.
 *     </li>
 * <li>{@link #TERMINATED}<br>
 *     A thread that has exited is in this state.
 *     </li>
 * </ul>
 *
 * <p>
 * A thread can be in only one state at a given point in time.
 * These states are virtual machine states which do not reflect
 * any operating system thread states.
 *
 * @since   1.5
 * @see #getState
 */
public enum State {
    /**
     * Thread state for a thread which has not yet started.
     */
    NEW,

    /**
     * Thread state for a runnable thread.  A thread in the runnable
     * state is executing in the Java virtual machine but it may
     * be waiting for other resources from the operating system
     * such as processor.
     */
    RUNNABLE,

    /**
     * Thread state for a thread blocked waiting for a monitor lock.
     * A thread in the blocked state is waiting for a monitor lock
     * to enter a synchronized block/method or
     * reenter a synchronized block/method after calling
     * {@link Object#wait() Object.wait}.
     */
    BLOCKED,

    /**
     * Thread state for a waiting thread.
     * A thread is in the waiting state due to calling one of the
     * following methods:
     * <ul>
     *   <li>{@link Object#wait() Object.wait} with no timeout</li>
     *   <li>{@link #join() Thread.join} with no timeout</li>
     *   <li>{@link LockSupport#park() LockSupport.park}</li>
     * </ul>
     *
     * <p>A thread in the waiting state is waiting for another thread to
     * perform a particular action.
     *
     * For example, a thread that has called <tt>Object.wait()</tt>
     * on an object is waiting for another thread to call
     * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
     * that object. A thread that has called <tt>Thread.join()</tt>
     * is waiting for a specified thread to terminate.
     */
    WAITING,

    /**
     * Thread state for a waiting thread with a specified waiting time.
     * A thread is in the timed waiting state due to calling one of
     * the following methods with a specified positive waiting time:
     * <ul>
     *   <li>{@link #sleep Thread.sleep}</li>
     *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
     *   <li>{@link #join(long) Thread.join} with timeout</li>
     *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
     *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
     * </ul>
     */
    TIMED_WAITING,

    /**
     * Thread state for a terminated thread.
     * The thread has completed execution.
     */
    TERMINATED;
}

5.线程状态转换方式

(1)NEW -> RUNNABLE -> TERMINATED

import lombok.extern.slf4j.Slf4j;
import java.util.Timer;
import java.util.TimerTask;

@Slf4j
class DiyThread extends Thread {
    public DiyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println("HelloWorld!");
    }
}
@Slf4j
public class Main {
    public static void main(String[] args) {
        DiyThread diyThread = new DiyThread("线程一");
        log.info("1 - Thread:{} state:{}", diyThread.getName(), diyThread.getState()); // NEW

        diyThread.start();
        log.info("2 - Thread:{} state:{}", diyThread.getName(), diyThread.getState()); // RUNNABLE

        // 启动后,先延时0秒,再每500毫秒执行一次任务
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                log.info("Thread:{} state:{}", diyThread.getName(), diyThread.getState());
            }
        }, 0, 500);
    }
}

(2)NEW -> RUNNABLE -> TIMED_WAITING -> RUNNABLE -> TERMINATED

import lombok.extern.slf4j.Slf4j;
import java.util.Timer;
import java.util.TimerTask;

@Slf4j
class DiyThread extends Thread {
    public DiyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        try {
            // 检查线程的中断状态
            while (!interrupted()) {
                Thread.sleep(1000);
            }
        } catch (InterruptedException interruptedException) {
            System.out.println("捕获 InterruptedException 异常 => " + interruptedException);
        } finally {
            log.info("Thread:{} state:{}", Thread.currentThread().getName(), Thread.currentThread().getState());
        }
    }
}
@Slf4j
public class Main {
    public static void main(String[] args) {
        DiyThread diyThread = new DiyThread("线程一");
        log.info("Thread:{} state:{}", diyThread.getName(), diyThread.getState()); // NEW

        diyThread.start();
        log.info("Thread:{} state:{}", diyThread.getName(), diyThread.getState()); // RUNNABLE

        // 程序启动后,开始计算,第5秒后执行中断操作
        new Timer().schedule(new TimerTask() {
            public void run() {
                /**
                 * 通知`线程一`执行中断操作
                 * 当一个线程调用 interrupt() 方法时,如果该线程正在执行可中断的方法(如:sleep、wait、join等),
                 * 那么它会立即受到一个 InterruptedException 异常,并且中断状态会被清除。这个异常可以让线程有机会
                 * 进行清理操作,然后终止线程的执行。
                 */
                diyThread.interrupt();
            }
        }, 5000);

        // 启动后,先延时0秒,再每500毫秒执行一次任务
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                log.info("Thread:{} state:{}", diyThread.getName(), diyThread.getState());
            }
        }, 0, 500);
    }
}

(3)NEW -> RUNNABLE -> BLOCKED -> TIMED_WAITING -> RUNNABLE -> TERMINATED

import lombok.extern.slf4j.Slf4j;
import java.util.Timer;
import java.util.TimerTask;;

@Slf4j
public class Main {
    static Object money = new Object();
    
    public static void main(String[] args) throws InterruptedException {
        DiyThread diyThread = new DiyThread("线程一");
        DiyThread diyThreadCopy = new DiyThread("线程二");
        log.info("1 - Thread:{} state:{}", diyThread.getName(), diyThread.getState()); // NEW
        log.info("1 - Thread:{} state:{}", diyThreadCopy.getName(), diyThreadCopy.getState()); // NEW

        diyThread.start();
        diyThreadCopy.start();
        log.info("2 - Thread:{} state:{}", diyThread.getName(), diyThread.getState()); // RUNNABLE
        log.info("2 - Thread:{} state:{}", diyThreadCopy.getName(), diyThreadCopy.getState()); // RUNNABLE

        // 启动后,先延时0秒,再每500毫秒执行一次任务
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                log.info("Thread:{} state:{}", diyThread.getName(), diyThread.getState());
                log.info("Thread:{} state:{}", diyThreadCopy.getName(), diyThreadCopy.getState());
            }
        }, 0, 500);
    }

    @Slf4j
    static
    class DiyThread extends Thread {
        public DiyThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            synchronized (money) {
                try {
                    System.out.println(Thread.currentThread().getName() + " -> 睡眠开始");
                    Thread.sleep(5000); // 线程一在5秒内都持有锁
                    System.out.println(Thread.currentThread().getName() + " -> 睡眠结束");
                } catch (InterruptedException interruptedException) {
                    interruptedException.printStackTrace();
                }
            }
            log.info("Thread:{} state:{}", Thread.currentThread().getName(), Thread.currentThread().getState());
        }
    }
}

二、在Java中创建线程的方式

1.继承Thread方式

import lombok.extern.slf4j.Slf4j;
import java.util.Timer;
import java.util.TimerTask;

@Slf4j
class DiyThread extends Thread {
    public DiyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        int i = 0;
        try {
            while (!interrupted()) {
                Thread.sleep(500);
                log.info("Thread:{} state:{} run:{}", Thread.currentThread().getName(), Thread.currentThread().getState(), ++i);
            }
        } catch (InterruptedException e) {
            log.info("Thread:{} state:{} run:{}", Thread.currentThread().getName(), Thread.currentThread().getState(), ++i);
            e.printStackTrace();
        }
    }
}
@Slf4j
public class Main {
    public static void main(String[] args) throws InterruptedException {
        DiyThread diyThread1 = new DiyThread("线程一");
        DiyThread diyThread2 = new DiyThread("线程二");

        diyThread1.start();
        diyThread2.start();

        // 睡眠等待3秒
        // Thread.sleep(3000);
        // diyThread1.interrupt(); // 通知`线程一`执行中断操作
        // log.info("3秒后,通知`线程一`执行中断操作");

        // 延时等待3秒
        new Timer().schedule(new TimerTask() {
            public void run() {
                diyThread1.interrupt(); // 通知`线程一`执行中断操作
                log.info("3秒后,通知`线程一`执行中断操作");
            }
        }, 3000);
    }
}

2.实现Runnable接口方式

import lombok.extern.slf4j.Slf4j;

@Slf4j
class DiyThread implements Runnable {
    @Override
    public void run() {
        int i = 0;
        try {
            while (!Thread.currentThread().isInterrupted()) {
                Thread.sleep(500);
                log.info("Thread:{} state:{} run:{}", Thread.currentThread().getName(), Thread.currentThread().getState(), ++i);
            }
        } catch (InterruptedException e) {
            log.info("Thread:{} state:{} run:{}", Thread.currentThread().getName(), Thread.currentThread().getState(), ++i);
            e.printStackTrace();
        }
    }
}
@Slf4j
public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread diyThread1 = new Thread(new DiyThread());
        Thread diyThread2 = new Thread(new DiyThread());
        diyThread1.setName("线程一");
        diyThread2.setName("线程二");
        diyThread1.start();
        diyThread2.start();

        // 睡眠等待3秒
        Thread.sleep(3000);
        diyThread1.interrupt(); // 通知`线程一`执行中断操作
        log.info("3秒后,通知`线程一`执行中断操作");
    }
}

3.带返回值的线程方式

import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

@Slf4j
class DiyCallable implements Callable<Integer> {
    @Override
    public Integer call() {
        try {
            Thread.sleep(2000);
            log.info("Thread:{} state:{}", Thread.currentThread().getName(), Thread.currentThread().getState());
            return 1;
        } catch (Exception e) {
            log.info("Thread:{} state:{}", Thread.currentThread().getName(), Thread.currentThread().getState());
            return 0;
        }
    }
}
@Slf4j
public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        DiyCallable diyCallable = new DiyCallable();
        FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>) diyCallable);
        Thread thread = new Thread(task);
        thread.setName("带返回值的线程");
        thread.start();
        Integer res = task.get();
        System.out.println(res);
    }
}

4.定时器的线程

import lombok.extern.slf4j.Slf4j;
import java.util.Timer;
import java.util.TimerTask;

@Slf4j
public class Main {
    public static void main(String[] args) {
        Timer timer = new Timer();
        // 启动后,先延时5秒,再每2秒执行一次任务
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                log.info("Thread:{} state:{}", Thread.currentThread().getName(), Thread.currentThread().getState());
            }
        }, 5000, 2000);
    }
}

5.Lambda的线程使用方式

import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.List;

@Slf4j
public class Main {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(50, 20, 30, 10, 40);
        System.out.println(testStream(list));
        System.out.println(testParallelStream(list));
    }

    private static int testStream(List<Integer> list) {

        long startTime = System.currentTimeMillis();
        list.stream().forEach(System.out::println);
        long endTime = System.currentTimeMillis();
        int sum = list.parallelStream().mapToInt(i -> i * 2).sum();
        System.out.println("list.stream() -> 耗时:" + (endTime - startTime));
        return sum;
    }

    private static int testParallelStream(List<Integer> list) {
        // parallelStream的优势是:充分利用多线程,提高程序运行效率。
        long startTime = System.currentTimeMillis();
        list.parallelStream().forEach(System.out::println);
        int sum = list.parallelStream().mapToInt(i -> i * 2).sum();
        long endTime = System.currentTimeMillis();
        System.out.println("list.parallelStream() -> 耗时:" + (endTime - startTime));
        return sum;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值