当前位置: 首页 > news >正文

Java线程

一,程序,进程,线程

程序:安装在电脑上的程序文件    是静态的

进程:运行中的应用程序,例如运行中的qq。。。。。。,是操作系统分配空间的最小单位

线程:进程可以进一步细化成线程,就是进程中最小的任务单元
      cpu执行以线程为单位


    线程和进程关系:
        一个进程中可以包含多个线程,线程不能脱离进程.
        一个进程中至少包含一个线程(主线程    main)
        在主线程中可以创建并启动其他线程        
        
        main方法启动主线程
        在一个线程中的方法顺序进行
        

二,创建线程

1.继承Thread()类方法

在Java中要实现线程,最简单的方法就是继承Thread类,重写其中的run方法,方法原型如下

package javatheard.demo1;

public class MyThread  extends  Thread{
    /*
        线程中要执行的代码或任务都在run()中
     */

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("run"  + i );
        }
    }
}

Thread类中的run()方法本身并不执行任何操作,如果我们重写run方法,当线程启动时,它将执行run方法

package javatheard.demo1;

public class Test {
    /*
        启动java的主线程
     */

    public static void main(String[] args) {
        //创建一个线程
        MyThread myThread = new MyThread();
        myThread.start();//启动线程

        //此for循环属于main线程
        for (int i = 0; i < 1000; i++) {
            System.out.println("main" + i);
        }
    }
}

2.实现Runnable接口方法

java.lang.Runnable接口中仅仅只有一个抽象方法

public  void  run()

也可以通过实现Runnable接口的方式来实现线程,只需要实现其中的run方法即可

Runnable接口的存在主要是为了解决Java中不允许多继承的问题

package javatheard.demo2;

public class Task implements Runnable{
    /*
        实现了Runnable接口的类,并不是线程
        是把要执行的任务放在此类的run()中,这个类就可以看出一个任务类
     */
    public static void main(String[] args) {

    }

    /*
        run()写线程要执行的任务
     */
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println(i);
        }
    }
}
package javatheard.demo2;

public class Test {

    public static void main(String[] args) {
        Task task = new Task();//创建一个任务对象
        Thread thread1 = new Thread(task);//创建一个线程对象,并添加一个要执行的任务1
        Thread thread2 = new Thread(task);//创建一个线程对象,并添加一个要执行的任务2
       thread1.start();
       thread2.run();//只实现方法与线程无关
        for (int i = 0; i < 1000; i++) {
            System.out.println(i);
        }
    }
}

Runnable接口方式的好处

(1)避免了单继承的局限性

(2)多个线程可以共享同一个接口实现类的对象,非常适合多个相同线程类处理同一份资源

三,Thread类中的常用方法

Thread.sleep(2000);//使该线程休眠多少毫秒
Thread thread1 = new Thread(task,"窗口一");//使用线程,并命名
thread1.setPriority(6);//设置优先级
thread1.setName("jh1");//给对应线程修改名称
System.out.println( Thread.currentThread().getPriority()+"    "+Thread.currentThread().getId()+"    "+Thread.currentThread().getName());
            //返回线程优先级,ID,线程名称
thread1.join();//等待线程结束

线程优先级:

        计算机中只有一个cpu,各个线程轮流获得cpu的使用权,才能执行任务

        优先级较高的线程有更多获得cpu的机会

        优先级使用整数表示,取值范围是1~10;默认情况下优先级为5

        Thread类中有3个静态常量表示优先级

        MAX_PRIORITY:取值范围为10,表示最高优先级

        MIN_PRIORITY:取值为1,表示最低优先级

        NOPM_PRIORITY:取值为5,表示默认优先级

注:高优先级线程抢占cpu

四,线程状态

新建:当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态

就绪:处于新建状态的线程被start()后,将进入线程队列等待cpu时间片,此时它已具备了运行时条件,只是没分配到cpu资源

运行:当就绪的线程被调度并获得cpu资源时,便进入运行状态,run()方法定义了线程的操作和功能

阻塞:在某种特殊情况下,被认为挂起或执行输入输出操作时,让出cpu并临时终止自己的执行,进入阻塞状态

死亡:线程完成了它的全部工作或线程被提前强制地中止或出现异常导致结束

五,多线程的概念

多线程是指程序中包含多个执行单元,即在一个程序中可以同时运行多

个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行

执行的线程来完成各自的任务。

1.何时需要多线程

(1)程序需要同时执行两个或多个任务时

(2)程序需要实现一些需要等待的任务时,如用户输入,文件读写操作,网络操作,搜索等

2.多线程的优点

(1)提高程序的响应

(2)提高cpu的利用率

(3)改善程序结构,将复杂任务分为多个线程,独立执行

3.多线程的缺点

线程也是程序,所以线程需要占用内存,线程越多占用内存也越多;

多线程需要协调和管理,所以需要跟踪管理线程,使得cpu开销变大;

线程之间同时对共享资源的访问会相互影响,如果不加以控制会导致数据出错.

六,线程同步

1.多线程同步

多个线程同时读写同一份共享资源时,可能会引起冲突。所以引入线程“同步”机制,

即各线程间要有先来后到;

注:同步就是排队+锁:

几个线程之间要排队,一个个对共享资源进行操作,而不是同时进行操作;

2.同步锁

为了保证数据在方法中被访问时的正确性,在访问时加入锁机制

       同步锁可以是java中任意的类的一个对象,此对象必须是唯一的,
       此对象时用来记录有没有线程进入到同步代码块中
       synchronized(同步锁){
       }
       一旦有线程进入到同步代码中,同步锁对象就会记录,其他线程就不能进入,
       直到进入同步代码块的线程执行离开同步代码块,锁会自动释放
        synchronized修饰方法,这个方法为同步方法,
           这时同步锁对象就不需要我们自己提供了,会自己提供
           当方法如果是非静态方法时,锁对象是this
           当方法如果是静态方法时,锁对象是类对象(类对象一个类只有一个)
      public static synchronized void print(){
      }
 

七,新增创建线程方法

实现Callable接口与使用Runnable相比,Callable功能更加强大些

(1)相比run()方法,可以有返回值

(2)方法可以抛出异常

(3)支持泛型的返回值

(4)需要借助FutereTask类,获取返回结果

package javatheard.Demo8;

import java.util.concurrent.Callable;

/*
    java中第三种创建线程方式,实现Callable接口
    重写call()方法
      进行了升级
        1.可以返回结果
        2.可以抛出异常
 */
public class SumTask implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        Integer a = 0;
        for (int i = 0; i <= 10; i++) {
            a+=i;
        }
        return a;
    }
}
package javatheard.Demo8;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Test {


    public static void main(String[] args) {
        SumTask sumTask = new SumTask();//创建任务对象
        FutureTask<Integer> futureTask = new FutureTask<>(sumTask);//创建一个FutureTask对象接受Callable接口的实现类
        Thread thread = new Thread(futureTask);//创建线程,接受一个任务
        thread.start();//接收线程
        try {
            Integer a = futureTask.get();//获取线程返回值
            System.out.println(a);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
    }
}

相关文章:

  • MySQL知识点
  • ollama API 本地调用
  • tsfresh:时间序列特征自动提取与应用
  • CCF CSP 第30次(2023.09)(2_坐标变换(其二)_C++)
  • rc4算法简单介绍及实现
  • 堆(Heap)和栈(Stack),这两者通常是指内存管理中两种不同的内存区域
  • Docker系列——从零开始打包FunASR的Http服务
  • PECL(Positive Emitter-Coupled Logic)电平详解
  • 我的世界1.20.1forge开发进阶教程——生物AI(1)
  • ctfshow-xxs-316-333-wp
  • 酒店宾馆IPTV数字电视系统:创新宾客体验,引领智慧服务新潮流
  • SpringCloud系列教程(十四):Sentinel持久化
  • 自动化测试:PO模式
  • DaVinci Resolve(达芬奇)快捷键大全
  • windows 启用linux子系统不必再装双系统
  • 剑指 Offer II 086. 分割回文子字符串
  • 力扣665. 非递减数列 475.供暖屋
  • Windows功能之FTP服务器搭建
  • orm bee/Orm bee/Orm Bee (CSDN还区分大小写)
  • IMX6ULL学习整理篇——Linux驱动开发的基础2 老框架的一次实战:LED驱动
  • 马上评丨行人转身相撞案:走路该保持“安全距离”吗
  • 胳膊一抬就疼,炒菜都成问题?警惕这种“炎症”找上门
  • 如此城市|上海老邬:《爱情神话》就是我生活的一部分
  • 对话哭泣照被恶意盗用成“高潮针”配图女生:难过又屈辱
  • 陈丹燕:赤龙含珠
  • 李彦宏:技术迭代速度之快从业30年来未见过,要提升执行力战胜对手