首页 > 其他分享 >多线程简单介绍

多线程简单介绍

时间:2024-01-27 10:34:22浏览次数:29  
标签:Thread int void 介绍 线程 简单 多线程 public

线程:是操作系统能够进行运算调度的最小单位。它被包含在进程中,是进程中实际运作单位
进程:进程是程序的基本执行实体,一个程序就是一个进程

简单理解线程:
应用软件中相互独立,可以同时运行的功能
有了多线程,就可以让程序同时做多件事

线程的生命周期
完整的线程状态
New(新建状态) ->创建线程对象
至今尚未启动的线程处于这种状态

RUNNABLE(就绪状态) ->start方法
在Java虚拟机中执行的线程处于此状态

BLOCKER(阻塞状态) ->无法获得锁对象
被阻塞等待监视器锁定的线程处于此状态

WAITING(等待状态) ->wait方法
无限期的等待另一个线程执行特定动作的线程处于此状态

TIMED_WAITING(计时状态) ->sleep方法
正在等待另一个线程执行动作达到指定等待时间的线程处

TERMINATED(结束状态) ->全部代码运行完毕
已退出的线程处于此状态

多线程的实现方式
1.继承Thread类的方式进行实现
2.实现Runnable接口的方式进行实现
3.利用Callable接口和Future接口方式实现

多线程的第一种启动方式
1.自己定义一个类继承Thread
2,重写run方法
3.创建子类的对象,并启动线程
例如

public class MyThread extends Thread{
  @Override
  public void run(){
    //书写线程要执行代码
    for(int i=0; i<100; i++){
      System.out.println(getName()+"HelloWord");
    }
  }
}

public class MyThreadTest{
  public static void main(String[] args){
    MyThread t1=new MyThread();
    MyThread t2=new MyThread();

    t1.setName("线程1");
    t2.setName("线程2");

    t1.start();
    t2.start();
  }
}

多线程的第二种启动方式
1.定义一个类实现Runnable接口
2.重写里面的run方法
3.创建自己类的对象
4.创建一个Thread类的对象,并开启线程
例如

public class MyRun implements Runnable{
  @Override
  public void run(){
    for(int i=0; i<100; i++){
      //获取到当前的对象
      //Thread t=Thread.currentThread();
      //System.out.println(t.getName()+"HelloWorld")
      System.out.println(Tread.currentThread.getName()+"HelloWorld");
    }
  }
}

public class MyRunnableTest{
  public static void main(String[] args){
    //创建MyRun的对象
    //表示多线程要执行的任务
    MyRun mr=new MyRun();

    //创建线程对象
    Thread t1=new Thread(mr);
    Thread t2=new Thread(mr);

    //给线程设置名字
    t1.setName("线程1");
    t2.setName("线程2");

    //开启线程
    t1.start();
    t2.start();
  }
}

多线程的第三种实现方式
特点:可以获取到多线程运行的结果
1.创建一个类MyCallable实现Callable接口
2.重写call(是有返回值的,表示多线程运行的结果)
例如

public class MyCallable implements Callable<Integer>{
  @Override
  public Integer call() throws Exception{
    //1~100之间的和
    int sum=0;
    for(int i =0; i<100;i++){
      sum+=i;
    }
    return sum;
  }
}

3.创建MyCallable的对象(表示多线程要执行的任务)
4.创建FutureTask的对象(作用管理多线程运行的结果)
5.创建Thread类的对象,并启动(表示线程)

public class ThreadDemo{
  public static void main(String[] args) throws ExcutionException{
    //创建MyCallable的对象(表示多线程要执行的任务)
    MyCallable mc =new MyCallable();

    //创建FuturnTask的对象(作用管理多线程运行的结果)
    FutureTask<Integer> ft =new FutureTask<>(mc);

    //创建线程的对象
    Thread t1 =new Thread(ft);
    //启动线程
    t1.start();

    //获取多线程运行的结果
    Integer result =ft.get();
    System.out.println(result);
  }
}

多线程三种实现方式对比
继承Thread类:
优点:编程比较简单,可以直接使用Thread类中的方法
缺点:扩展性较差,不能再继承其他的类

实现Runnable接口
优点:扩展性强,实现该接口的同时还可以继承其他的类
缺点:编程相对复杂,不能直接使用Thread类中方法

实现Callable接口
优点:
1.可以获取到多线程的运行的结果
2.扩展性强,实现该接口的同时还可以继承其他的类
确定:编程相对复杂,不能直接使用Thread类中的方法

Thread常见的成员方法

方法名称 说明
String getName() 返回此线程的名称
void setName(String name) 设置线程的名字(构造方法也可以设置名字)
static Thread currentThread() 获取当前线程的对象
static void sleep(long time) 让线程休眠指定的时间,单位为毫秒
setPriority(int new Priority) 设置线程的优先级
final int getPriority() 获取线程的优先级
final void setDaemon(boolean on) 设置为守护线程
public static void yield() 出让线程/礼让线程
public static void join() 插入线程/插队线程
方法名称 说明
String getName() 返回此线程的名称
void setName(String name) 设置线程的名字(构造方法也可以设置名字)

细节:
1.如果我们没有给线程设置名字,线程也是有默认的名字的
格式:Thread-X(X为序号,从0开始)
2.如果我们要给线程设置名字,可以用set方法进行设置,也可以用构造方法进行设置
注意:子类要使用父类的有参构造器,要先生成有参构造器

方法名称 说明
More Actions static Thread currentThread() 获取当前线程的对象

细节:
当JVM虚拟机启动之后,会自动的启动多条线程
其中有一天线程就叫做main线程,作用就是调用main方法并执行里面的代码
在以前,我们写的所有代码,其实都运行在main线程当中

方法名称 说明
static void sleep(long time) 让线程休眠指定的时间,单位为毫秒

细节:
1.哪条线程执行到这个方法,那么哪条线程就会在这里停留对应的时间
2.方法的参数:就表示睡眠的时间,单位毫秒 1秒=1000毫秒
3.当时间到了之后,线程会自动的醒来,继续执行下面的其他代码

方法名称 说明
setPriority(int new Priority) 设置线程的优先级
final int getPriority() 获取线程的优先级

细节:Java是抢占式调度,体现了随机性
多个线程抢夺cpu的执行权,cpu在什么时候执行哪条线程是不确定的,执行多长时间也是不确定的
没有设置线程的优先级,默认为5,最小权重为1,最大权重为10
权重越大随机到的概率越大,但不是100%

方法名称 说明
final void setDaemon(boolean on) 设置为守护线程

细节:当其他的非守护线程执行完毕之后,守护线程会陆续结束
简单来说:当女神线程结束了,那么备胎也就没有存在的必要了

public class MyThread1 extends Thread{
  @Override
  public void run(){
    for(int i=1;i<=10;i++){
      System.out.println(getName()+"@"+i);
    }
  }
}

public class MyThread2 extends Thread{
  @Override
  public void run(){
    for(int i=1; i<=100; i++){
      System.out.println(getName()+"@"+i);
    }
  }
}

public class ThreadDemo{
  public static void main(String[] args){
    MyThread t1 =new MyThread1();
    MyThread t2 =new MyThread2();

    t1.setName("女神");
    t2.setName("备胎");

    //把第二个线程设置为守护线程(备胎线程)
    t2.setDaemon(true);

    t1.start();
    t2.start();
    //女神运行10次时,备胎就会停止运行,不会执行到100次
  }
}

守护线程应用场景
例如:聊天和传输文件,聊天是一个线程,传输文件也是一个线程
当聊天关闭,那么传输文件也应该关闭,可以把传输文件设置为守护线程

方法名称 说明
public static void yield() 出让线程/礼让线程

作用:为了让结果分布更加均匀,但不是绝对
举例

public class MyThread extends Thread{
  @Override
  public void run(){
    for(int i=1; i<=100;i++){
      System.out.println(getName()+"@"+i);
      //表示出让当前CPU的执行权
      //线程会重新抢夺CPU的执行权
      Thread.yield();
    }
  }
}

public class ThreadDemo{
  public static void main(String[] args){
    MyThread t1 = new Thread();
    MyThread t2 = new Thread();

    t1.setName("飞机");
    t2.setName("坦克");

    t1.start();
    t2.start();
  }
}
方法名称 说明
public static void join() 插入线程/插队线程

举例

public class MyThread extends Thread{
  @Override
  public void run(){
    for(int i = 1; i<=100; i++){
      System.out.println(getName()+"@"+i);
    }
  }
}

public class ThreadDemo{
  public static void main(String[] args){
    MyThread t = new MyThread();
    t.setName("土豆");
    t.start();

    //表示把t这个线程插入当前线程之前
    //t:土豆
    //当前线程:main线程
    //土豆线程执行完才执行main线程
    t.join();

    //执行在main线程当中的
    for(int i = 0; i<10; i++){
      System.out.println("main线程"+i);
    }
  }
}

标签:Thread,int,void,介绍,线程,简单,多线程,public
From: https://www.cnblogs.com/zhao-zong-yu-hai/p/17990766

相关文章

  • 多线程sleep、yield、wait、join方法的使用和区别
    使用和介绍sleep方法sleep方法的官方注释(翻译后):/***根据系统计时器和调度程序的精度和准确性,使当前执行的线程休眠(暂时停止执行)指定的毫秒数。线程不会失去任何监视器的所有权(不释放锁)。**@parammillis以毫秒为单位的睡眠时间长度*@throws......
  • MFC 定时器的简单用法
    View下两个消息事件:ON_WM_CREATEON_WM_TIMERBEGIN_MESSAGE_MAP(CMFCApplication1View,CView)//标准打印命令ON_COMMAND(ID_FILE_PRINT,&CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT,&CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW,&a......
  • Vue-router 子路由(嵌套路由)介绍
    在Vue.js应用程序中,路由是实现单页面应用(SPA)导航的关键。Vue-router是Vue.js官方的路由管理器,提供了声明式的路由配置方式。子路由是一种路由组织方式,允许开发者将路由嵌套在父路由下,形成层次化的路由结构。这种结构有助于更好地组织和管理复杂的应用程序。子路由的使用场......
  • 简单使用vim编辑器的用法
    vim的使用笔记可以涵盖很多内容,以下是一些基本操作和常见命令的简要总结:启动Vim打开或创建文件:vimfilename基本模式切换正常模式(NormalMode):启动时默认进入此模式,用于执行移动、复制、删除等操作。进入插入模式:按下i、a、o或O键(在光标前/后插入文本、新行下方/上方......
  • Pytest 源码解读 [1] - [pluggy] 插件框架介绍
    Pluggy(https://github.com/pytest-dev/pluggy)Pytest的核心实际的基于 Pluggy 这个pluginframework的,实际上pytest本身就是由一个一个插件组成的本来pluggy的代码是在pytest的repo里,后来迁移了出来,作为一个独立的项目。Pluggy作为一个独立的pluginframework......
  • 1.JAVA基础-JDK的介绍
    Java语言语言:人与人交流沟通的表达方式。计算机语言:人与计算机之间进行信息交流沟通的一种特殊语言。Java语言是美国Sun公司(StanfordUniversityNetwork)在1995年推出的计算机语言。Java之父:詹姆斯·高斯林(JamesGosling)。Java语言的三个版本⚫JavaSE⚫JavaME......
  • 简单定时任务实现
     在Java中,可以使用java.util.Timer或java.util.concurrent.ScheduledExecutorService类来实现定时任务。以下是使用java.util.Timer实现定时任务的示例代码: 1publicclassMyTimerTaskextendsTimerTask{2@Override3publicvoidrun(){4//......
  • selenium介绍及编写用例
    Selenium 是一个用于自动化测试Web应用程序的工具集。它可以模拟用户在浏览器中的操作,例如点击按钮、填写表单、登录等。Selenium支持多种浏览器,包括 Chrome、Firefox、IE等,并提供了多种编程语言的API,例如 Python、Java、C#等。使用Selenium,开发人员可以编写自动化测试脚......
  • V4l2 简单介绍和使用
    概述:Videoforlinux2(简称V4L2),是linux中关于视频设备的内核驱动。它也是linux操作系统下用于采集图片、视频和音频数据的API接口,配合适当的视频采集设备和相应的驱动程序;作用:支持许多USB网络摄像头,电视调谐器和相关设备,使它们的输出标准化,因此程序员可以轻松地向其应用程序......
  • 【C++】 select函数介绍
    在使用C++语言开发网络应用程序时,常常需要用到select函数。select函数是一种多路复用机制,可以同时监听多个文件描述符上可读、可写、异常等事件,从而让程序能够高效地处理多个连接。下面详细介绍C++中的select函数。1.select函数的定义和作用select函数的定义为:intselect(intn......