如何在Java中创建和启动线程?线程同步的方法有哪些?

本文详细介绍了Java中创建线程的三种方式:继承Thread类、实现Runnable接口和Callable接口,并讨论了线程同步的synchronized关键字、ReentrantLock类和同步代码块的应用,以防止数据竞争和保证线程安全。
摘要由CSDN通过智能技术生成

1 在Java中创建和启动线程有三种常用的方法:

1.1 继承Thread类: 创建一个继承自Thread类的子类,并重写其run()方法来定义线程要执行的任务。然后通过调用子类的start()方法来启动线程。

/**
* 优点:使用继承方式的好处是, 在run() 方法内获取当前线程直接使用this 就可以了,无须使用Thread. currentThread() 方法;
* 缺点:1)Java 不支持多继承,如果继承了Thread 类,那么就不能再继承其他类。2)任务与代码没有分离, 当多个线程执行一样的任务时需要多份任务代码。3)任务没有返回值。
*/
public class ThreadTest {
//底层Thread也是实现Runnable接口
	public static class MyThread extends Thread{
    	@Override
    	public void run() {
        	System.out.println(this.getName()+" 运行体");
    	}
	}
	public static void main(String[] args)throws Exception{
    	//创建线程
    	MyThread myThread=new MyThread();
    	myThread.setName("子线程0");

    	//启动线程  调用start方法后线程并没有马上执行而是处于就绪状态,这个就绪状态是指该线程已经获取除CPU资源外的其他资源,等待获取CPU资源后才会真正处于运行状态,一旦run方法执行完成,该线程就处于终止状态
    	myThread.start();

	}
}

1.2 实现Runnable接口: 创建一个实现了Runnable接口的类,并实现其run()方法来定义线程要执行的任务。然后将该类的实例传递给Thread类的构造函数,并调用Thread实例的start()方法来启动线程。

/**
* @Description:实现Runnable接口的run方法
* @Title:RunableTask
* 优点:1)两个线程共用一个task 代码逻辑,如果需要,可以给RunableTask添加参数进行任务区分。2) RunableTask 可以继承其他类。
* 缺点:任务没有返回值。
* @Package com.example.thread
* @Author:wyf
* @CreateTime:2024/2/2215:31
*/
public class RunableTask implements Runnable{
	@Override
	public void run() {
    	System.out.println(Thread.currentThread().getName()+" 运行体");
	}
	public static void main(String[] args)throws Exception{
    	//创建线程
    	RunableTask task=new RunableTask();
    	Thread thread1=new Thread(task);
    	thread1.setName("线程1");
    	thread1.start();
    	Thread thread2=new Thread(task);
    	thread2.setName("线程2");
    	thread2.start();
	}
}

1.3 实现Callable接口: 创建一个实现了Callable接口的类,实现了Callable 接口的call()方法。在main 函数内首先创建了一个Futrue Task 对象( 构造函数为实现callable接口的类 的实例) , 然后使用创建的FutrueTask对象作为任务创建了一个线程并且启动它, 最后通过futureTask.get() 等待任务执行完毕并返回结果

/**
* @Description:有返回值的线程
* @Title:CallableTask
* @Package com.example.thread
* @Author:wyf
* @CreateTime:2024/2/2215:47
*/
public class CallableTask implements Callable<Object> {
	@Override
	public Object call() throws Exception {
    	return Thread.currentThread().getName()+" 运行体";
	}
	public static void main(String[] args)throws Exception{
    	//创建异步任务
    	FutureTask<Object> futureTask=new FutureTask<>(new CallableTask());
    	//创建线程
    	Thread thread1=new Thread(futureTask);
    	thread1.setName("线程1");
    	//启动线程
    	thread1.start();

    	try{
        	//等待任务执行完毕,并返回结果
        	String result= (String) futureTask.get();
        	System.out.println(result);
    	}catch (Exception e){
        	e.printStackTrace();
    	}
	}
}

2 线程同步的方法有以下几种:

2.1 使用synchronized关键字:**可以使用synchronized关键字来同步方法或代码块,确保同时只有一个线程访问被同步的代码区域。

class MyThread {
   private int count = 0;

   public synchronized void increment() {
       count++;
   }
}

2.2 使用ReentrantLock类:**ReentrantLock类提供了与synchronized关键字相似的功能,但更加灵活,允许实现更复杂的同步结构。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class MyThread {
   private int count = 0;
   private Lock lock = new ReentrantLock();

   public void increment() {
       lock.lock();
       try {
           count++;
       } finally {
           lock.unlock();
       }
   }
}

2.3 使用synchronized代码块:**除了同步整个方法外,还可以使用synchronized关键字来同步代码块,以减少同步的范围。

class MyThread {
   private int count = 0;

   public void increment() {
       synchronized (this) {
           count++;
       }
   }
}

这些方法都可以确保多个线程在访问共享资源时保持互斥,避免了数据竞争和不一致的结果。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值