简单介绍创建线程的几种方式

1.继承Thread类

先看代码

  • 创建线程类
//创建一个类,继承Thread
public class myThread extentce Thread{
	//重写Thread类中的run()方法,(run方法中写自己的业务逻辑)
	@Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("i = " + i);
        }
    }
}
  • 定义一个测试类
public class ThreadDemo {
	public static void main(Stirng[] args){
		//创建自定义线程类的子类对象
		myThread t = new myThread();
		//调用start()方法开启线程
		t.start();

		//主方法任务
		for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"i = " + i);
        }
	}
}
  • 注意说明
    1.不可以使用线程类对象直接调用run()方法,这样只是普通的调用方法,不会开启线程.只能使用线程对象调用start()方法开启,交由jvm执行.
    2.不要直接创建Thread线程对像,对象再调用start()方法开启线程,这样操作也可以开启线程,但是Thread类中的run()方法没有被重写,就没有任何业务逻辑,毫无意义.
    3.创建线程的目的?
    建立程序单独执行的路径,可以让多个任务同时执行,在业务里使用线程,我们要给他指定要执行的任务才有意义.
    4.多线程的内存运行
    多线程执行任务时,每个线程在栈内存中,都有一片自己的运行空间,进行方法的压栈和弹栈,当某个线程任务执行完成后,就自动在内存中释放掉了,当所有线程任务执行完毕之后,进程也就结束了.
    5.获取线程的名称
    currentThread():返回当前线程对象的引用,
    getName():返回线程名称。
    String name = Thread.currentThread().getName();

2.实现Runnable接口

  • 创建线程类实现Runnable接口
public class MyThread implements Runnable {
    //重写run()方法
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("线程"+ Thread.currentThread().getName() + i);
        }
    }
}
  • 定义测试类
public class ThreadDemo{
	public static void main(String[] args){
		//创建自定义线程类对象
		MyThread  t = new MyThread ();
		//创建线程对象,传入自定义线程类对象
		Thread thread = new Thread( t )
		//开启线程
		thread.start();

		//主方法业务代码
		for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + i);
        }
	}
}
  • 注意说明
    1.继承Thread类和实现Runnable接口的区别
    实现Runnable接口可以避免单继承Thread类的局限性,而且只有创建Thread类对象才可以使用开启线程,线程任务已被封装到Runnable接口的run()方法中,该接口所属Runnable接口的子类对像,把子类对象作为参数传递到Thread类的构造方法中,线程对象创建时就可以明确要执行的线程任务。
    2.实现Runnable接口的好处
    一般最常用的创建线程的方式就是实现Runnable接口,即避免了单继承的局限性,又更加符合面向对象思想,把线程分为两部分,一部分是线程对象,一部分是线程任务。继承Thread类,线程对象和线程任务耦合在一起。实现Runnable接口,将线程任务单独分离出来封装成对象,Runnable接口对线程任务和线程对像进行解耦.

3.使用线程池

3.1实现Runnable接口的方式

  • 使用线程池的好处
    在业务中,每个请求都创建一个线程的话,开销是非常大的.创建和销毁线程会消耗大量的系统资源,如果在一个jvm里创建太多线程,可能会导致系统过度消耗内存而资源不足.我们就要采取一些办法尽可能的减少线程创建和销毁的次数.线程池就是用来解决线程生命周期开销问题和资源不足问题.通过对多个任务重复使用线程,线程创建的开销就会被分摊到多个任务上,由于在请求到达时线程已经存在,所以消除了线程创建时带来的延迟,就可以立即为请求服务,使程序响应更快,而且适当的调整线程的数目可以防止出现资源不足的情况.

  • 线程池都是由线程池工厂创建,再调用线程池中的方法获取线程,再通过线程去执行任务.

    Executors:线程池创建工厂类
    public static ExecutorService newFixedThreadPool(int nThreads):返回线程池对象
    ExecutorService:线程池类
    Future<?> submit(Runnable task):获取线程池中的某一个线程对象,并执行
    Future接口:用来记录线程任务执行完毕后产生的结果。线程池创建与使用

  • 实现Runnable接口,使用线程池

public class ThreadDemo{
	public static void main(String[] args){
		//创建线程池对象 指定线程数量
		ExecutorService service = Executors.newFixedThreadPool(2);
		//创建线程类对象
		MyThread t = new MyThread();
		//从线程池中获取线程对象 传入自定义线程类对象
		service.submit(demo);
        service.submit(demo);
		//submit方法调用结束后,程序并不终止,是因为线程池控制了线程的关闭。将使用完的线程又归还到了线程池中,需要手动关闭.
		service.shutdown();
	}
}
  • 自定义线程类
public class MyThread implements Runnable {
	@Override
    public void run() {
      System.out.println("来把锤子");

		try {
	            Thread.sleep(2000);
	        } catch (InterruptedException e) {
	            e.printStackTrace();
	        }
	        System.out.println("锤子来了");
	         System.out.println("锤子用完之后放回工具箱里.");
	    }
}

3.2 实现callable接口的方式

Callable接口:与Runnable接口功能相似,用来指定线程的任务。其中的call()方法,用来返回线程任务执行完毕后的结果,call方法可抛出异常。
ExecutorService:线程池类
Future submit(Callable task):获取线程池中的某一个线程对象,并执行线程中的call()方法
Future接口:用来记录线程任务执行完毕后产生的结果。线程池创建与使用.

使用步骤:
(1):创建线程池对象
(2):创建callable接口的子类对象
(3):提交callable接口的子类对象
(4):关闭线程池

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值