Java中线程的基本使用

158 阅读2分钟

线程的基本使用

Java 中线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程中可以并发多个线程,多条线程并行执行不同的任务。

创建线程的方式

继承 Thread 类的方式:

定义一个线程类,继承 Thread 类,重写 run () 方法,将线程要执行的任务写在 run () 方法中,然后创建该类的实例,调用 start () 方法启动线程。

实现 Runnable 接口的方式:

定义一个类,实现 Runnable 接口,实现 run () 方法,将线程要执行的任务写在 run () 方法中,然后创建该类的实例,再创建一个 Thread 类的实例,将 Runnable 实例作为参数传递给 Thread 构造器,最后调用 Thread 实例的 start () 方法启动线程。

线程的几种状态

新建(New):创建了一个线程对象,但还没有调用 start () 方法。

就绪(Runnable):调用了 start () 方法,等待 CPU 的调度。

运行(Running):获得了 CPU 的执行权,正在执行 run () 方法中的代码。

阻塞(Blocked):由于某些原因放弃了 CPU 的执行权,暂停执行。例如等待输入输出完成,或者等待获取同步锁。

终止(Terminated):run () 方法执行完毕或者出现异常而结束。

线程的主要概念

线程同步:当多个线程访问共享资源时,为了保证数据的一致性和完整性,需要使用同步机制来协调线程之间的操作顺序和执行时间。

线程间通信:当多个线程需要协作完成某个任务时,需要使用 wait ()、notify ()、notifyAll () 等方法来实现线程之间的交互和协调。

线程死锁:当多个线程互相持有对方需要的资源而不释放时,导致所有线程都无法继续执行的情况。

线程控制:当需要暂停、停止或恢复某个线程时,可以使用 suspend ()、stop ()、resume () 等方法来控制线程的状态。

代码示例

通过实现 Runnable 接口

// 定义一个类,实现 Runnable 接口  
class PrintNumberRunnable implements Runnable {  
    private int number;  
    // 重写 run () 方法  
    public void run() {  
        while(number<100){  
            System.out.println(Thread.currentThread().getName()+":输出数字 "+number++);  
            try {  
                Thread.sleep(500);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
}  
  
// 创建该类的实例  
PrintNumberRunnable printNumberRunnable = new PrintNumberRunnable();  
// 创建一个 Thread 类的实例  
Thread thread = new Thread(printNumberRunnable);  
// 给线程设置名字  
thread.setName("printNumberRunnable");  
// 调用 start () 方法启动线程  
thread.start(); 

定义一个类,实现 Runnable 接口,重写 run () 方法,将线程要执行的任务写在 run () 方法中,然后创建该类的实例,再创建一个 Thread 类的实例,将 Runnable 实例作为参数传递给 Thread 构造器,最后调用 Thread 实例的 start () 方法启动线程。

通过继承 Thread 类

// 定义一个类,继承 Thread 类  
class PrintNumberThread extends Thread {  
    private int number;  
    // 重写 run () 方法  
    public void run(){  
        while(number<100){  
            System.out.println(Thread.currentThread().getName()+":输出数字 "+number++);  
            try {  
                Thread.sleep(500);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
}  
  
// 创建该类的实例  
PrintNumberThread printNumberThread = new PrintNumberThread();  
// 给线程设置名字  
printNumberThread.setName("printNumberThread");  
// 调用 start () 方法启动线程  
printNumberThread.start();  

定义一个类,继承 Thread 类,重写 run () 方法,将线程要执行的任务写在 run () 方法中,然后创建该类的实例,调用该实例的 start () 方法启动线程。

通过 Callable 和 Future 接口

// 定义一个类,实现 Callable 接口  
class SumTask implements Callable<Integer> {  
    private int n;  
    public SumTask(int n) {  
        this.n = n;  
    }  
    // 重写 call () 方法  
    public Integer call() throws Exception {  
        int sum = 0;  
        for (int i = 1; i <= n; i++) {  
            sum += i;  
        }  
        return sum;  
    }  
}  
  
// 创建该类的实例  
SumTask sumTask = new SumTask(100);  
// 创建一个 ExecutorService 类的实例  
ExecutorService executorService = Executors.newSingleThreadExecutor();  
// 使用 submit () 方法提交 Callable 实例,并返回一个 Future 对象  
Future<Integer> future = executorService.submit(sumTask);  
// 调用 Future 对象的 get () 方法获取线程的返回值  
try {  
    System.out.println("1+2+...+100=" + future.get());  
} catch (Exception e) {  
    e.printStackTrace();  
}  
// 关闭线程池  
executorService.shutdown();

定义一个类,实现 Callable 接口,重写 call () 方法,将线程要执行的任务和返回值写在 call () 方法中,然后创建该类的实例,再创建一个 ExecutorService 类的实例,使用 submit () 方法提交 Callable 实例,并返回一个 Future 对象,最后调用 Future 对象的 get () 方法获取线程的返回值。