Java多线程是Java语言中的一项重要特性。多线程允许程序并发执行多个任务,让程序能够更高效地利用计算资源和提高相应速度。本文将从多个方面阐述Java多线程基础,包括线程创建、状态转换、同步与锁、线程池等。
一、线程创建
Java多线程的创建有两种方式:继承Thread类和实现Runnable接口。推荐使用实现Runnable接口的方式,因为这种方式可以更好地遵循面向对象设计原则,以及可以避免Java不支持多重继承的问题。
1. 继承Thread类
public class MyThread extends Thread { public void run() { // 这里放置线程需要执行的代码 } } // 创建线程实例并启动 MyThread myThread = new MyThread(); myThread.start();
上述代码定义了一个线程类MyThread,重写了父类Thread中的run()方法,该方法中存放了线程需要执行的方法。创建线程实例后,调用start()方法启动线程。需要注意的是,直接调用run()方法不会启动一个新的线程,而是在当前线程中执行run()方法。
2. 实现Runnable接口
public class MyRunnable implements Runnable { public void run() { // 这里放置线程需要执行的代码 } } // 创建线程实例并启动 MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.start();
上述代码定义了一个实现了Runnable接口的线程类MyRunnable。创建线程实例时,传入实例化的MyRunnable对象,并调用该线程的start()方法启动线程。
二、线程状态转换
线程在执行的过程中会发生状态,常见的状态有5种:新建状态、可运行状态、阻塞状态、等待状态、终止状态。线程状态转换如下:
1. 线程状态获取
线程状态可以使用getState()方法获得。该方法返回一个Thread.State枚举值,该枚举中定义了线程的所有状态。示例代码如下:
Thread thread = new Thread(() -> { // 执行任务 }); thread.start(); Thread.State state = thread.getState(); // 获取线程状态
2. 线程状态转换演示
通过以下代码,可以演示线程状态的转换过程:
public class ThreadDemo { public static void main(String[] args) throws Exception { Thread t = new Thread(() -> { System.out.println(Thread.currentThread().getName()+"线程已启动"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"线程已结束"); }); System.out.println(t.getName()+" 线程状态:"+t.getState()); // NEW t.start(); System.out.println(t.getName()+" 线程状态:"+t.getState()); // RUNNABLE Thread.sleep(500); System.out.println(t.getName()+" 线程状态:"+t.getState()); // TIMED_WAITING Thread.sleep(1000); System.out.println(t.getName()+" 线程状态:"+t.getState()); // TERMINATED } }
运行结果:
Thread-0 线程状态:NEW Thread-0 线程状态:RUNNABLE Thread-0 线程状态:TIMED_WAITING Thread-0 线程状态:TERMINATED
三、同步与锁
在多线程运行中,可能存在多个线程同时访问共享资源的情况,会导致数据不一致的问题。为了避免这种情况,需要使用同步与锁机制。
1. synchronized同步
synchronized是一种保证线程安全的机制,它可以修饰方法和代码块。在方法上添加synchronized关键字,可以实现对整个方法的同步。
public synchronized void synchronizedMethod() { // synchronize方法体 }
在代码块上添加synchronized关键字,可以实现对指定代码块的同步。
public void method(){ synchronized(this){ // synchronize代码块 } }
2. Lock锁机制
Lock是JDK提供的另一种线程同步机制,相比synchronized,Lock锁更加灵活,能够实现更细粒度的锁定。一个Lock锁可以同时被多个线程持有,线程使用完后必须释放锁。
Lock lock = new ReentrantLock(); lock.lock(); // 上锁 try { // lock代码块 } finally { lock.unlock(); // 释放锁 }
四、线程池
在进行多线程编程时,经常使用线程池来提高执行效率。Java语言提供了线程池的支持,可以充分利用CPU,提高程序的执行效率。
1. ThreadPoolExecutor
ThreadPoolExecutor是Java中的线程池实现,它可以自动管理和调度线程,并且可以实现线程池定制化,非常灵活。以下是ThreadPoolExecutor的构造函数:
ThreadPoolExecutor( int corePoolSize, // 线程池中核心线程数 int maximumPoolSize, // 线程池中最大线程数 long keepAliveTime, // 非核心线程空闲时间 TimeUnit unit, // keepAliveTime的单位 BlockingQueueworkQueue, // 任务队列 ThreadFactory threadFactory, // 线程工厂 RejectedExecutionHandler handler // 任务被拒绝时的处理方式 )
2. 线程池示例
以下代码演示了如何使用线程池实现多线程:
ExecutorService executorService = Executors.newFixedThreadPool(5); for(int i = 0; i < 10; i++) { executorService.execute(() -> { // 执行任务 }); } executorService.shutdown();
以上代码创建了一个FixedThreadPool类型的线程池,指定了线程池中核心线程数为5,最大线程数为5,当线程空闲时间达到1秒时,非核心线程将被回收。线程池接受10个任务,通过execute()方法执行任务,线程池在执行完任务后将被关闭。
总结
本文介绍了Java多线程的基础知识,包括线程的创建、状态转换、同步与锁、线程池等方面。通过学习和实践,可以更好地掌握Java多线程编程。