Java多线程(二)

Java多线程

创建多线程

  • 继承Thread类,实现多线程
    • java里面提供了一个java.lang.Thread的程序类,一个类只要继承此类就表示这个类为线程的主体类,然后覆写Thread类中的run()方法(public void run()),此方法就是线程的主方法。eg:
class MyThread extends Thread {//线程主体类
     private String title;
     public MyThread(String title) {
       this.title = title;
     }
      @Override
      public void run() {//线程的主体方法
        for(int x = 0; x < 10 ; x++) {
            System.out.println(this.title + "运行,x = " + x);
        }
      }
}


public class ThreadDemo {
    public static void main(String[] args) {
        new MyThread("线程A").start();
        new MyThread("线程B").start();
        new MyThread("线程C").start();
    }
}
  • 基于Runnable接口实现多线程
    • 虽然可以通过Thread类的继承来实现多线程的定义,但是在Java程序里面对于继承永远都是存在有单继承局限的,所以在Java里面又提供有第二种多线程的主体定义结构形式:实现java.lang.Runnable接口;eg:
class MyThread implements Runnable {//线程主体类
   private String title;
   public MyThread(String title) {
       this.title = title;
   }
   @Override
   public void run() {//线程的主体方法
       for(int x = 0; x < 10 ; x++) {
           System.out.println(this.title + "运行,x = " + x);
       }
   }
}
public class ThreadDemo {
   public static void main(String[] args) {
       Thread threadA = new Thread(new MyThread("线程A"));
       Thread threadB = new Thread(new MyThread("线程B"));
       Thread threadC = new Thread(new MyThread("线程C"));
       threadA.start();
       threadB.start();
       threadC.start();
   }
}
可以发现从JDK1.8开始,Runnable接口使用了函数式接口定义,所以    
也可以直接利用Lambda表达式进行线程类的实现定义。eg:
public class ThreadDemo {
    public static void main(String[] args) {
        for( int x = 0; x < 3 ; x ++) {
            String title = "线程对象-" + x;
                Runnable runnable = () ->{
                    for(int y = 0; y < 10 ; y ++) {
                        System.out.println(title + "运行,y = " + y);
                }
            };
                new Thread(runnable).start();
        }
    }
}
在以后的开发中对于多线程的实现,优先考虑Runnable接口实现,并且永恒都是通
过Thread类对象启动多线程。多线程开发的本质实质上是在于多个线程可以进行统一资源的抢占,那么Thread主要描述的是线程,
那么资源的描述是通过Runnable完成的。

实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源,注意每个线程都是用同一个实例化对象;eg:

class Thread2 implements Runnable{
 private int count=15;
 @Override
 public void run() {
 	  for (int i = 0; i < 5; i++) {
 		  System.out.println(Thread.currentThread().getName() + "运行  count= " + count--);
             try {
             	Thread.sleep((int) Math.random() * 10);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
         }
 	
 }
 
}
public class Main {

 public static void main(String[] args) {
 	
 	Thread2 my = new Thread2();
         new Thread(my, "C").start();//同一个mt,但是在Thread中就不可以,如果用同一个实例化对象mt,就会出现异常   
         new Thread(my, "D").start();
         new Thread(my, "E").start();
 }

}

2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立

  • Callable实现多线程
    • Callbale定义的时候可以设置一个泛型,此泛型的类型就是返回数据的类型,这样的的好处是可以避免向下转行所带来的安全隐患。
    • 线程执行完毕后,可以获取一个返回值
    • eg:
class MyThread2 implements Callable<String> {
   @Override
   public String call() throws Exception {
       for ( int x = 0 ; x < 10 ; x ++ ) {
           System.out.println("******线程执行,x = " + x);
       }
       return "线程执行完毕!";
   }
}
public class demo {
   public static void main(String[] args) throws Exception{
       FutureTask futureTask = new FutureTask(new MyThread2());
       new Thread(futureTask).start();
       System.out.println("线程返回值:" + futureTask.get());
   }
}
  • 线程池
    • 使用线程池原因:经常创建销毁线程,耗资靡费,对性能影响很大。

    • 原理:提前创建好多个线程,放入线程池,用时获取,用完放回。(数据库连接池)

    • 优点:及时响应,降低资源耗费,便于管理

    • 主要属性:corePoolSize:核心池的大小 maximumPoolSize:最大线程数 keepAliveTime:线程没有任务时最多保持多长时间后会终止

    • 线程池API:ExecutorService 和 Executors

      ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor.
      void execute(Runnable coommand):执行任务/命令,没有返回值,一般用来执行Runnable
      Futuresubmit(Callable task):执行任务,有返回值,一般又来执行Callable
      void shutdown():关闭连接池。
      Executors.newCachedThreadPool()	创建一个可根据需要创建新线程的线程池
      Executors.newFixedThreadPool(n)	创建一个可重用固定线程数的线程池
      Executors.newSingleThreadExecutor()	:创建一个只有一个线程的线程池
      Executors.newScheduledThreadPool(n)	创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
      
    • 线程池构造批量线程代码:

/**
* 创建线程的方式四:使用线程池(批量使用线程)
*1.需要创建实现runnable或者callable接口方式的对象
* 2.创建executorservice线程池
* 3.将创建好的实现了runnable接口类的对象放入executorService对象的execute方法中执行。
* 4.关闭线程池
*
* */

class NumberThread implements Runnable{


   @Override
   public void run() {
       for(int i = 0;i<=100;i++){
           if (i % 2 ==0 )
           System.out.println(Thread.currentThread().getName()+":"+i);
       }
   }
}

class NumberThread1 implements Runnable{
   @Override
   public void run() {
       for(int i = 0;i<100; i++){
           if(i%2==1){
               System.out.println(Thread.currentThread().getName()+":"+i);
           }
       }
   }
}

public class ThreadPool {

   public static void main(String[] args){

       //创建固定线程个数为十个的线程池
       ExecutorService executorService = Executors.newFixedThreadPool(10);

       //new一个Runnable接口的对象
       NumberThread number = new NumberThread();
       NumberThread1 number1 = new NumberThread1();

       //执行线程,最多十个
       executorService.execute(number1);
       executorService.execute(number);//适合适用于Runnable

       //executorService.submit();//适合使用于Callable
       //关闭线程池
       executorService.shutdown();
   }

}
  • 参考文章
    https://blog.csdn.net/taojin12/article/details/85544403
    https://blog.csdn.net/weixin_44797490/article/details/91006241
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值