多线程与线程安全,实现多线程的三种方法

创建线程的方式:


继承 Thread 类创建线程类

一、定义 Thread 类的子类,并重写该类的 run 方法,该 run 方法的方法体就代表了线程要完成的任务。因此把 run() 方法称为执行体。
创建 Thread 子类的实例,即创建了线程对象。
调用线程对象的 start() 方法来启动该线程。
通过 Runnable 接口创建线程类

public class ThreadTest extends Thread{
    public void run(){
        System.out.println("Thread Test Started");
    }
    public static void main(String[] args) {
        ThreadTest threadTest=new ThreadTest();
        threadTest.start();
    }
}
 

二、定义 Runnable 接口的实现类,并重写该接口的 run() 方法,该 run() 方法的方法体同样是该线程的线程执行体。
创建 Runnable 实现类的实例,并依此实例作为 Thread 的 target 来创建 Thread 对象,该 Thread 对象才是真正的线程对象。
调用线程对象的 start() 方法来启动该线程。
通过 Callable 和 Future 创建线程


public class RunnableTest implements Runnable{

    @Override
    public void run() {
        System.out.println("Runnable Test started");        
    }
    public static void main(String[] args) {
        RunnableTest runnableTest=new RunnableTest();
        Thread thread =new Thread(runnableTest);
        thread.start();
    }
}

三、创建 Callable 接口的实现类,并实现 call() 方法,该 call() 方法将作为线程执行体,并且有返回值。
创建 Callable 实现类的实例,使用 FutureTask 类来包装 Callable 对象,该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值。
使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程。
调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值

public class CallableTest implements Callable<String> {

    @Override
    public String call() throws Exception {        
        return "Callable Test started";
    }
    public static void main(String[] args) {
        ExecutorService threadPool=Executors.newSingleThreadExecutor();
        Future<String> future=threadPool.submit(new CallableTest());
        try {
            System.out.println("waiting thread to finish");
            System.out.println(future.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

三种创建多线程方式的比较

采用实现 Runnable、Callable 接口的方式创见多线程时:

优势是:线程类只是实现了 Runnable 接口或 Callable 接口,还可以继承其他类。在这种方式下,多个线程可以共享同一个 target 对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将 CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
劣势是:编程稍微复杂,如果要访问当前线程,则必须使用 Thread.currentThread() 方法。
使用继承 Thread 类的方式创建多线程时:

优势是:编写简单,如果需要访问当前线程,则无需使用 Thread.currentThread() 方法,直接使用 this 即可获得当前线程。
劣势是:线程类已经继承了 Thread 类,所以不能再继承其他父类。 

线程安全是多线程领域的问题,线程安全可以简单理解为一个方法或者一个实例可以在多线程环境中使用而不会出现问题。

 

在 Java 多线程编程当中,提供了多种实现 Java 线程安全的方式:

  • 最简单的方式,使用 Synchronization 关键字
  • 使用 java.util.concurrent.atomic 包中的原子类,例如 AtomicInteger
  • 使用 java.util.concurrent.locks 包中的锁
  • 使用线程安全的集合 ConcurrentHashMap
  • 使用 volatile 关键字,保证变量可见性(直接从内存读,而不是从线程 cache 读)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值