有关多线程的一些基本知识

今天简单来说一下多线程方面的一些基本知识概念
首先来介绍一下进程和线程:
进程:操作系统中一个程序的执行周期。
比如说打开QQ,就相当于启动了一个进程。点了QQ上面的×,就相当于关闭了这个进程。
线程:一个程序同时执行多个任务,通常来讲,每一个任务就是一个线程。
继续用QQ举例,当你打开QQ后,在你给别人发消息的同时,你也能接收到别人发给你的消息,这里就同时启动了两个线程,读线程和写线程,你给别人发消息,说明写线程在运作,同时你又能读到别人发给你的消息,说明读线程也在运作。而这两个线程是可以同时进行,并且互不干扰的。
那么,进程和线程又有什么联系呢?3个方面来说明:
(1)与进程相比,线程更加轻量级,即创建或撤销一个线程比启动撤销一个进程开销要小得多,一个进程中所有线程共享此进程所有资源。
(2)没有进程就没有线程,进程一旦终止,其内的线程也将不复存在
(3)进程是操作系统资源调度的基本单位,进程可以独享资源,线程需依托进程提供的资源,无法独立申请操作系统资源,是OS任务执行的基本单位。
知道了进程和线程的概念,接下来来看看多线程如何去实现。
Java多线程的实现有3种方式:

(1)继承Thread类实现多线程
Java.lang.Thread是线程操作的核心类,创建一个线程最简单的方法就是直接继承Thread,而后覆写run()方法(相当于主线程的main()方法)。

class MyThread extends Thread{ //线程主体类
    private String title;
    public MyThread1(String title){
        this.title=title;
    }
    @Override
    public void run(){  //所有线程从此处开始执行
        for(int i=0;i<5;i++){
            System.out.println(this.title+",i="+i);
        }
    }
}

(2)实现Runnable接口来实现多线程

class MyThread implements Runnable { // 线程主体类  
     private String title ;   
     public MyThread(String title) {  
          this.title = title;
     }  
    @Override   
    public void run() { // 所有线程从此处开始执行   
        for (int i = 0; i < 10 ; i++) {      
            System.out.println(this.title+",i = " + i);     
        }  
     } 
 }

继承Thread类与实现Runnable接口的关系 :
A. Thread类实现了Runnable接口,Thread类与自定义的线程类(实现了Runnable接口)是一个典型的代理设计模式。Thread类负责辅助真实业务(资源调度,创建线程并启动),自定义线程类负责真实业务的实现(run方法具体要做啥事)
B. 使用Runnable接口实现的多线程程序类可以更好地描述共享的概念。

(3)实现Callable接口实现多线程
当线程有返回值时,只能使用Callable接口实现多线程

class MyThread implements Callable<String> { 
     private int ticket = 10 ; // 一共10张票    
     @Override    
     public String call() throws Exception {
         while(this.ticket>0){ 
              System.out.println("剩余票数:"+this.ticket -- );  
         }       
         return "票卖完了,下次吧。。。" ;   
     } 
}
public class TestDemo {   
      public static void main(String[] args) throws InterruptedException, ExecutionException {      
           FutureTask<String> task = new FutureTask<>(new MyThread()) ;   
           new Thread(task).start();   
           new Thread(task).start();    
           System.out.println(task.get()); 
       } 
} 

在这里插入图片描述
Juc-JDK1.5新增的并发程序编程包
Java.util.concurrent.Callable实现Callable而后覆写call()方法。
注意:call()方法有返回值
划重点:无论哪种方式实现多线程,线程启动一定调用Thread类提供的start()方法。
但由于callable接口并没有提供可以传Thread类的方法,因此无法直接调用start();这时怎么办呢?FutureTask的出现正好打通了Thread与callable不能直接转换的障碍,上述代码中,用task接收了它的返回值并将其转换为Thread类,然后调用start()方法,于是该线程被启动。
Future接口:取得Callable接口的返回值
V get() throws InterruptedException,ExecutionException;

注意:线程的start()方法只能调用一次,多次调用会java.lang.IllegalThreadStartException异常
再来讨论一个问题:线程启动为什么要调用start()方法而不是run()方法,如果调用run()方法会怎样?要回答这个问题,先来看看下面这张图:
在这里插入图片描述
线程调用Start()方法后,start()方法会调用start0()方法,这时操作系统会进行资源调度,系统分配,然后再由JVM调用run(java方法)执行线程的具体操作任务。也就是说,调用start()方法后,JVM 会为线程的启动做一些准备工作,而如果直接调用run()方法,没有系统资源的调度与分配这个过程,那么run()方法执行后的效果就相当于是一个普通方法的执行,多个线程之间也是一个执行完毕后另一个才执行,并不能体现出多线程的并发执行效果。

好了,今天就先写到这,后续还会继续更新更多有关多线程方面的知识。如果写的有问题的地方,还请大家多多指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值