多线程(一)(多线程一定要加锁么)

  本篇文章为你整理了多线程(一)(多线程一定要加锁么)的详细内容,包含有多线程一定比单线程快吗 多线程一定要加锁么 多线程一定快吗 多线程一般应用场景 多线程(一),希望能帮助你了解 多线程(一)。

  大佬的理解- Java多线程(一)多线程基础

  大佬的理解- Java多线程(二)常用的实现多线程的两种方式

  1、继承Thread类

  ​ 继承Thread必须重写run方法,(具体业务执行方法,需要执行的业务方法,定义在此方法中),注意此方法是线程启动后线程自动调用的;

  案例

  

public class MyThread extends Thread{

 

   @Override

   public void run() {

   //线程执行的业务方法

   System.out.println("子线程执行");

   for (int i = 0;i i++){

   System.out.println("--- 线程名---:"+Thread.currentThread().getName()+",序号:"+i);

   public static void main(String[] args) {

   //主线程

   System.out.println("***主线程执行***");

   System.out.println("***线程名***:"+Thread.currentThread().getName());

   //创建一个线程并启动,只能通过主线程创建其他线程

   MyThread thread1 = new MyThread();

   MyThread thread2 = new MyThread();

   //启动线程:start()方法(一旦启动,自动启动子线程,当前线程继续向下执行,不会等子线程)

   thread1.start();

   //启动多线程

   //多线程并发执行:不是正真一样上的并行执行(肉眼感官是并行),而是通过cpu的调度算法,有序cpu执行极快,所以肉眼看起来是并行的;

   thread2.start();

   //调用run方法,不可以启动线程,就是对象的普通方法调用,等run方法执行结束,主线程才能继续执行

   //thread1.run();

   //thread2.run();

   System.out.println("----主线程执行结束----");

  

 

  运行结果

  调用start()方法

  

***主线程执行***

 

  ***线程名***:main

  ----主线程执行结束----

  子线程执行

  --- 线程名---:Thread-0,序号:0

  --- 线程名---:Thread-0,序号:1

  --- 线程名---:Thread-0,序号:2

  --- 线程名---:Thread-0,序号:3

  --- 线程名---:Thread-0,序号:4

  子线程执行

  --- 线程名---:Thread-1,序号:0

  --- 线程名---:Thread-1,序号:1

  --- 线程名---:Thread-1,序号:2

  --- 线程名---:Thread-1,序号:3

  --- 线程名---:Thread-1,序号:4

  

 

  调用run()方法

  

***主线程执行***

 

  ***线程名***:main

  子线程执行

  --- 线程名---:main,序号:0

  --- 线程名---:main,序号:1

  --- 线程名---:main,序号:2

  --- 线程名---:main,序号:3

  --- 线程名---:main,序号:4

  子线程执行

  --- 线程名---:main,序号:0

  --- 线程名---:main,序号:1

  --- 线程名---:main,序号:2

  --- 线程名---:main,序号:3

  --- 线程名---:main,序号:4

  ----主线程执行结束---- //必须等子线程完成后才可以继续运行

  

 

  注意start()方法和run()方法的区别

  start():启动线程start()方法(一旦启动,自动启动子线程,当前线程继续向下执行,不会等子线程);
 

  run() :调用run方法,不可以启动线程,只是对象的普通方法调用,等run方法执行结束,主线程才能继续执行;

  2、实现Runnable接口

  实现Runnable接口,也必须实现run方法;

  案例

  

public class MyRunnable implements Runnable{

 

   private int num = 5;

   @Override

   public void run() {

   //线程执行的业务方法

   System.out.println("子线程执行");

   for (int i = 0;i i++){

   if(num 0){

   System.out.println("--- 线程名---:"+Thread.currentThread().getName()+",序号:"+num--);

   public static void main(String[] args) {

   //主线程

   System.out.println("***主线程执行***");

   System.out.println("***线程名***:"+Thread.currentThread().getName());

   //创建一个子线程,并启动

   MyRunnable runnable1 = new MyRunnable();

   //实现Runnable接口方式创建的线程,不能自己启动,只能通过Thread类,将Runnable作为参数传入Thread类的构造方法中,

   // 构造线程对象,才可以启动

   Thread thread1 = new Thread(runnable1);

   thread1.start();

   //创建多线程 (如果传入的Runnable参数一样,可以共享资源)

   Thread thread2 = new Thread(runnable1);

   thread2.start();

   System.out.println("----主线程执行结束----");

  

 

  运行结果

  

***主线程执行***

 

  ***线程名***:main

  ----主线程执行结束----

  子线程执行

  子线程执行

  --- 线程名---:Thread-0,序号:5

  --- 线程名---:Thread-1,序号:4

  --- 线程名---:Thread-0,序号:3

  --- 线程名---:Thread-1,序号:2

  --- 线程名---:Thread-0,序号:1

  

 

  注意

  如果传入的Runnable参数一样,可以共享资源;

  3、比较两种创建线程的方式

  继承Thread类

  编写简单,可直接操作线程

  适用于单继承

  实现Runnable接口

  避免单继承局限性

  便于共享资源

  4、实现Callable接口

  4.1实现Callable接口调用的call方法

  创建线程的方式三,实现Callable接口,线程自动调用的时call方法,不是run方法,jdk1.5后才提供;

  4.2 FutureTask 类的继承关系

  执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。

  

//FutureTask V 是 RunnableFuture V 的实现类

 

  public class FutureTask V implements RunnableFuture V

  //RunnableFuture V 接口继承了 Runnable, Future V //所以FutureTask最后需要放到Thread参数中,这里跟继承Runnable方法一样;

  public interface RunnableFuture V extends Runnable, Future V ;

  

 

  类图

  4.3 案例

  

public class MyCallable implements Callable Integer {

 

   @Override

   public Integer call() throws Exception {

   System.out.println("***子线程执行***");

   //执行线程处理方法

   int sun = 0;

   for (int i = 0; i i++) {

   sun+=i;

   return sun;

   public static void main(String[] args) {

   //主线程执行

   System.out.println("---主线程执行---");

   //创建子线程,不可以自己单独启动,必须借助FutureTask才可以,必须获取子线程执行结果

   MyCallable callable = new MyCallable();

   FutureTask Integer futureTask = new FutureTask Integer (callable);

   //启动线程,只能借助Thread类

   Thread thread = new Thread(futureTask);

   thread.start();

   //获取子线程的执行结果(必须要子线程执行结束,才可以获取结果)

   try {

   Integer resultSun = futureTask.get(); //接收返回值

   System.out.println("五以内的数字之和:"+resultSun);

   } catch (Exception e) {

   e.printStackTrace();

   System.out.println("---主线程结束---");

  

 

  运行结果

  

---主线程执行---

 

  ***子线程执行***

  五以内的数字之和:10 //接收到返回值

  ---主线程结束---

  

 

  4.4 Callable和Runnable的区别

  1)所在包不同,Callable在java.util.concurrent包下,Runnable在java.lang包;

   2)实现的接口方法不同:Callable是重写call方法,Runnable的重写run方法;

  3)抛出异常处理不同:Callable是重写call方法,可以抛出异常,但是Runnable是重写run方法不可以抛出异 常,如果抛出线程直接中断;

  4)返回值不同:实现Callable接口的线程,可以通过FutureTask获取返回值,但是是实现Runnable接口的线程,无法获取返回值;

  以上就是多线程(一)(多线程一定要加锁么)的详细内容,想要了解更多 多线程(一)的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: