当前位置:网站首页>线程的实现方式总结

线程的实现方式总结

2022-07-06 09:23:00 飘飘~

提示:阅读本篇文章前,请先了解操作系统中线程和进程的基本概念。

线程基本概念本文会有所提及,操作系统和进程请参考我的这两篇笔记  https://note.youdao.com/s/ag3ipekEicon-default.png?t=M4ADhttps://note.youdao.com/s/ag3ipekE

            
https://note.youdao.com/s/BFTOv61yicon-default.png?t=M4ADhttps://note.youdao.com/s/BFTOv61y

目录

前言:

一、多线程的基础知识

 1.1 什么是线程

 1.2 何时需要多线程

 1.3 多线程的优缺点

 1.4 多线程的物种状态

二、线程的实现方式

 2.1 继承Thread类     

 2.2 实现Runnable接口

 2.3 实现Callable接口 

 2.4 线程池


前言:

在系统层面,为了减少操作的耗时,提高程序并行操作效率以及CPU的利用率,我们引入了多线程的技术概念。、

本文将从线程的基本概念讲起,详细介绍创建多线程的四种方式。

一、多线程的基础知识

 1.1 什么是线程

        线程是进程内部的一个可执行单元,是可以完成一个独立任务的顺序控制流程,如果在一个进程中同时运行多个线程,用来完成不同的工作,则称之为多线程。

 1.2 何时需要多线程

        (1)程序需要同时执行两个或两个以上任务时。

        (2)程序需要执行一些需要等待的任务时,比如用户注册,文件读写。

        (3)需要后台执行程序时。

 1.3 多线程的优缺点

        优点:

  • 能适当的提高程序的执行效率
  • 能适当提高资源利用率(cpu、内存利用率)

        缺点:

  • 开启线程需要占用一定的内存空间,(默认情况下,主线程1M,子线程512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能。
  • 线程越多,cpu在调度线程上的开销就越大。
  • 程序设计更加复杂:比如线程之间的通讯、多线程的数据共享

 1.4 多线程的物种状态

  1. NEW:新建状态。当一个线程被创建后,启动之前,就处于该状态。
  2. RUNNABLE:可运行状态。当一个线程正在执行任务,就处于该状态。
  3. WAITING:无限等待状态。一个线程获取Lock锁对象,失败,就处于该状态。
  4. TIMED_WAITING:计时等待状态。当一个线程正在执行sleep方法的时候,就处于该状态。
  5. BLOCKED:阻塞状态。一个线程获取synchronized(代码块、方法)锁对象,失败,就处于该状态。
  6. TERMINATED:消亡状态。当线程把任务执行结束后,就处于该状态。

其中NEW状态和TERMINATED状态只会出现一次。
 

二、线程的实现方式

创建子线程就是:创建Thread类型的对象,并启动执行。 

 2.1 继承Thread类     

        Thread类:
                  所属包:java.lang;
                  构造方法:
                      public Thread();
                      public Thread(Runnable target);
                      public Thread(Runnable target,String name);
                  静态方法:
                      static Thread currentThread();//获取当前线程,哪个线程执行该方法,就获取哪个线程
                  成员方法:
                      void start();//只能调用一次,不能调用多次
                      void run();//线程启动以后,会执行run方法中的代码
                      String getName();//获取线程的名称
                      void setName(String name);//设置线程的名称  

 继承Thread类创建线程的步骤如下:

  1. 创建一个继承于Thread类的子类。
  2. 重写Thread类的run方法–>将此线程执行的操作声明在run()中。
  3. 创建子类对象。
  4. 通过子类对象调用start()方法。

 创建Thread类的对象,重写run()方法的代码如下:

public class Test01Thread {
	public static void main(String[] args) {
		//以匿名内部类的方式创建Thread类型的对象,创建线程
		Thread t = new Thread() {
			@Override
			public void run() {
				String name = Thread.currentThread().getName();
				System.out.println(name);
			}
		};
		t.start();//启动线程
		
	};

}

 

 2.2 实现Runnable接口

        Runnable接口:

                Runnable比Thread类所具有的优势:
                  1.可以避免java中的单继承的局限性(java是单继承多级继承,而实现是多实现
                  2.任务和线程分离,实现了解耦合
                  3.线程池只能传入Runnable或者Callable类型的对象,不能使用继承的方式

 实现Runnable接口创建线程的步骤如下: 

  1. 创建一个实现了Runnable接口的类
  2. 实现Runnable接口中的方法。
  3. 创建实现类的对象。
  4. 将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象。
  5. 通过Thread类的对象调用start()方法。

  实现Runnable接口创建线程的代码如下:

public class Test02Runnable {
	public static void main(String[] args) {
		//采用匿名内部类的方式创建Runnable类型的对象
		Runnable r = new Runnable() {
			@Override
			public void run() {
				String name = Thread.currentThread().getName();
				System.out.println(name);
			}
		};
		
		//创建线程
		Thread t = new Thread(r,"线程1");
		t.start();
	}

}

 

 2.3 实现Callable接口 

         callable接口:

  实现Callable接口的步骤如下:

  1. 创建子类实现callable的实现类。
  2. 实现call方法,将此线程需要执行的操作声明在call方法中。
  3. 创建Callable接口对象
  4. 将此Callable实现类的对象作为参数传递到FutureTask构造器中,创建FutureTask对象。
  5. 将FutureTask类的序传递到Thread类的构造器中,创建Thread类的对象,通过该对象启动线程
  6. 可以获取Callable实现类的call方法的返回值。(可选,需要返回值就get,不需要就不get)   
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

public class Test03Callable {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		//通过匿名内部类的方式创建Callable类型的对象
		Callable<String> callable = new Callable<String>() {
			@Override
			public String call() throws Exception {
				System.out.println(Thread.currentThread().getName());
				return "存在返回值";
			}
		}; 
		
		//创建FutureTask对象接受callable返回值结果
		FutureTask<String> ft=new FutureTask(callable);
		
		//创建线程
		Thread t=new Thread(ft);
		
		//启动线程
		t.start();
		//获取线程的返回结果
		String str = ft.get();
		
		System.out.println(str);//测试Callable的返回值
	}

}

 2.4 线程池

        线程池创建线程:
         优点:
             1.降低资源消耗(减少了频繁的创建和销毁线程)。
                  线程池中的线程可以提前创建,而且只需完任务以后可以不销毁
             2.提高响应速度。 线程池中的线程可以提前创建线程。
             3.提高线程的可管理性。(任务很多,而且每个任务需要消耗的时间比较长)
              创建一个线程大约需要消耗1M的空间。
  
          语法:
              Executors类
                  static ExecutorService newFixedThreadPool(int c);//参数是线程的数量
  
              ExecutorService接口:
                  void execute(Runnable r);
                  Future<?> submit(Runnable r);//如果线程执行完任务后又返回值,则可以处理返回的结果
                  <T> Future<T> submit(Callable<T> c);
                  void shutdown();//关闭线程池
  
              Future<T>接口
                  T get();//必须等待子线程任务执行结束后,才可以获取到返回结果。

 实现Runnable接口,利用线程池创建线程。 

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test04Executors {
	public static void main(String[] args) {
		//创建固定线程池对象,2为创建两个线程.
		ExecutorService threadPool = Executors.newFixedThreadPool(2);
		
		Runnable r = new Runnable() {
			@Override
			public void run() {
				System.out.println(Thread.currentThread().getName());
			}
		};
		
		//执行任务
		threadPool.execute(r);
		
		//关闭
		threadPool.shutdown();
	}

}

 实现Callable接口,利用线程池创建线程,并获取返回值。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Test05ExecutorsCall {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		//创建线程池对象
		ExecutorService threadPool = Executors.newFixedThreadPool(1);
		
		//通过匿名内部类的方式创建Callable类型的对象
		Callable<String> callable = new Callable<String>() {
			@Override
			public String call() throws Exception {
				System.out.println(Thread.currentThread().getName());
				Thread.sleep(10000);
				return "有返回值";
			}
		}; 
		
		//执行任务
		Future<String> future = threadPool.submit(callable);
		//获取线程的返回结果。
		String str = future.get();
		
		System.out.println(str);//测试Callable的返回值
		
		//关闭
		threadPool.shutdown();
	}

}

 

 

最后,感谢大家的持续支持!!!

学而时习之,才能有所进步。

 

 

原网站

版权声明
本文为[飘飘~]所创,转载请带上原文链接,感谢
https://blog.csdn.net/m0_46420244/article/details/125119246