首页 > 系统相关 >线程与进程

线程与进程

时间:2024-08-12 14:48:52浏览次数:8  
标签:run Thread start 线程 进程 new ticket

多线程

多线程的创建方式

方式1:继承于Thread类

1.创建一个集成于Thread类的子类 (通过ctrl+o(override)输入run查找run方法)
2.重写Thread类的run()方法
3.创建Thread子类的对象
4.通过此对象调用start()方法

start与run方法的区别:

start方法的作用:1.启动当前线程 2.调用当前线程的重写的run方法(在主线程中生成子线程,有两条线程)
调用start方法以后,一条路径代表一个线程,同时执行两线程时,因为时间片的轮换,所以执行过程随机分配,且一个线程对象只能调用一次start方法。
run方法的作用:在主线程中调用以后,直接在主线程一条线程中执行了该线程中run的方法。(调用线程中的run方法,只调用run方法,并不新开线程)

package com.example.paoduantui.Thread;

import android.view.Window;

/**
 *
 * 创建三个窗口卖票,总票数为100张,使用继承自Thread方式
 * 用静态变量保证三个线程的数据独一份
 * 
 * 存在线程的安全问题,有待解决
 *
 * */

public class ThreadDemo extends Thread{

    public static void main(String[] args){
        window t1 = new window();
        window t2 = new window();
        window t3 = new window();

        t1.setName("售票口1");
        t2.setName("售票口2");
        t3.setName("售票口3");

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

}

class window extends Thread{
    private static int ticket = 100; //将其加载在类的静态区,所有线程共享该静态变量

    @Override
    public void run() {
        while(true){
            if(ticket>0){
//                try {
//                    sleep(100);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
                System.out.println(getName()+"当前售出第"+ticket+"张票");
                ticket--;
            }else{
                break;
            }
        }
    }
}

方式2:实现Runable接口方式

1.创建一个实现了Runable接口的类
2.实现类去实现Runnable中的抽象方法:run()
3.创建实现类的对象
4.将此对象作为参数传递到Thread类中的构造器中,创建Thread类的对象
5.通过Thread类的对象调用start()
package com.example.paoduantui.Thread;

public class ThreadDemo01 {
    
    public static  void main(String[] args){
        window1 w = new window1();
        
        //虽然有三个线程,但是只有一个窗口类实现的Runnable方法,由于三个线程共用一个window对象,所以自动共用100张票
        
        Thread t1=new Thread(w);
        Thread t2=new Thread(w);
        Thread t3=new Thread(w);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        
        t1.start();
        t2.start();
        t3.start();
    }
}

class window1 implements Runnable{
    
    private int ticket = 100;

    @Override
    public void run() {
        while(true){
            if(ticket>0){
//                try {
//                    sleep(100);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
                System.out.println(Thread.currentThread().getName()+"当前售出第"+ticket+"张票");
                ticket--;
            }else{
                break;
            }
        }
    }
}

比较创建线程的两种方式:
开发中,优先选择实现Runable接口的方式
原因1:实现的方式没有类的单继承性的局限性
2:实现的方式更适合用来处理多个线程有共享数据的情况
联系:Thread也是实现自Runable,两种方式都需要重写run()方法,将线程要执行的逻辑声明在run中

线程的分类:

java中的线程分为两类:1.守护线程(如垃圾回收线程,异常处理线程),2.用户线程(如主线程)

若JVM中都是守护线程,当前JVM将退出。(形象理解,唇亡齿寒)

线程的状态

线程的生命周期:

线程的生命周期阶段 说明
新建 当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态
就绪 处于新建状态的线程被start后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件,只是没分配到CPU资源
运行 当就绪的线程被调度并获得CPU资源时,便进入运行状态,run方法定义了线程的操作和功能
阻塞 在某种特殊情况下,被人为挂起或执行输入输出操作时,让出CPU并临时终止自己的执行,进入阻塞状态
死亡 线程完成了它的全部工作或线程被提前强制性地中止或出现异常导致结束

线程的安全问题:

什么是线程安全问题呢?

线程安全问题是指,多个线程对同一个共享数据进行操作时,线程没来得及更新共享数据,从而导致另外线程没得到最新的数据,从而产生线程安全问题。

方式一:同步代码块

使用同步监视器(锁)
Synchronized(同步监视器){
//需要被同步的代码
}
说明:

操作共享数据的代码(所有线程共享的数据的操作的代码)(视作卫生间区域(所有人共享的厕所)),即为需要共享的代码(同步代码块,在同步代码块中,相当于是一个单线程,效率低)
共享数据:多个线程共同操作的数据,比如公共厕所就类比共享数据
同步监视器(俗称:锁):任何一个的对象都可以充当锁。(但是为了可读性一般设置英文成lock)当锁住以后只能有一个线程能进去(要求:多个线程必须要共用同一把锁,比如火车上的厕所,同一个标志表示有人)
Runable天生共享锁,而Thread中需要用static对象或者this关键字或者当前类(window。class)来充当唯一锁

方式二:同步方法

使用同步方法,对方法进行synchronized关键字修饰
将同步代码块提取出来成为一个方法,用synchronized关键字修饰此方法。
对于runnable接口实现多线程,只需要将同步方法用synchronized修饰
而对于继承自Thread方式,需要将同步方法用static和synchronized修饰,因为对象不唯一(锁不唯一)

总结:1.同步方法仍然涉及到同步监视器,只是不需要我们显示的声明。

方式三:JDK5.0新增的lock锁方法

package com.example.paoduantui.Thread;


import java.util.concurrent.locks.ReentrantLock;

class Window implements Runnable{
    private int ticket = 100;//定义一百张票
    //1.实例化锁
    private ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        
            while (true) {
    
                //2.调用锁定方法lock
                lock.lock();
    
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "售出第" + ticket + "张票");
                    ticket--;
                } else {
                    break;
                }
            }


        }

}

public class LockTest {

    public static void main(String[] args){
       Window w= new Window();
    
       Thread t1 = new Thread(w);
       Thread t2 = new Thread(w);
       Thread t3 = new Thread(w);
    
       t1.setName("窗口1");
       t2.setName("窗口1");
       t3.setName("窗口1");
    
       t1.start();
       t2.start();
       t3.start();
    }

}

总结:Synchronized与lock的异同?
相同:二者都可以解决线程安全问题
不同:synchronized机制在执行完相应的代码逻辑以后,自动的释放同步监视器
lock需要手动的启动同步(lock()),同时结束同步也需要手动的实现(unlock())(同时以为着lock的方式更为灵活)

优先使用顺序:
LOCK->同步代码块->同步方法

标签:run,Thread,start,线程,进程,new,ticket
From: https://www.cnblogs.com/chenlei210162701002/p/18354957

相关文章

  • linux下进程与计划任务管理
    linux下进程与定时任务的管理进程与程序程序:存储在硬盘、光盘等介质中含有可执行代码的可执行文件。不删除就永久存在。状态为静态。进程:进程是资源分配的最小单位。临时存储在内存中(关机消失)。动态执行的代码。一个父进程可以拥有多个子进程。若该进程的父进......
  • 关于异步编程和多线程的高级.NET Core面试题
    以下是一些关于异步编程和多线程的高级.NETCore面试题。这些问题涵盖了从基础概念到复杂应用的各个方面,可以帮助评估候选人在异步编程和多线程开发方面的能力。1.异步编程基础在.NETCore中,异步编程的基本原理是什么?async和await关键字的作用是什么?如何在.NETCore中使用......
  • Java线程池和执行流程
    在Java中,常见的四种线程池包括:1.newFixedThreadPool(固定大小线程池)应用场景:适用于需要限制线程数量,并且任务执行时间比较均匀的场景,例如服务器端的连接处理。优点:线程数量固定,能够有效地控制并发线程数,避免过多的线程竞争资源。缺点:如果线程在执行任务过程中出现异常......
  • Mac上的 WindowServer进程是什么?如何解决高CPU使用率
    大多数时候,我们不会关注Mac上运行的后台进程。但是,如果你在罕见的一天检查活动监视器以解决减速问题,你可能会惊讶地看到WindowServer进程位于顶部。想知道Mac上的WindowServer有什么用?它为什么要吃资源?接下来带大家了解关于WIndowServer的一些知识以及它是否安全。Mac......
  • 通过cmd查找端口占用,并杀死进程
    windows通过cmd查找端口占用1.查看端口占用情况netstat-ano 2.查看某个端口被占用情况netstat-ano|findstrxxxx//xxxx为查询的端口号 3.查看某个状态的端口netstat-ano|findstrxxxx//xxxx为查询的端口状态 具体端口状态请查找后面描述......
  • 线程与多线程
    1.线程1.线程状态线程状态分为5种newrunable->分为ready和running阻塞等待->分为waiting和time_waiting销毁1.2线程数量配置IO密集型=CPU*2cpu密集型=CPU+12.线程池2.1线程池核心参数线程池一共7个核心参数,分别是核心线程数、最大线程数......
  • 进程间通信IPC
    前言        进程是操作系统中独立运行的程序单元,每个进程拥有自己的内存空间。由于进程之间的内存空间是隔离的,不能直接访问彼此的内存,因此需要借助IPC来实现进程间的数据交换一.管道进程间通信的本质是让不同的进程看到同一份资源, 我们先来看管道是如何做到的......
  • 9 - Linux进程和计划任务管理
    目录一、进程1.程序和进程的关系2.查看进程信息2.1ps命令-查看进程信息2.2top命令-查看进程的动态信息2.3pgrep命令-查找进程信息2.4jobs命令-查看后台进程状态信息3.进程的启动方式4.进程的前后台调度5.中止进程的运行5.1Ctrl+C组合键5.2kill......
  • Linux:线程同步机制(互斥锁、读写锁、条件变量、信号量详细分析总结)
    目录速览1、互斥锁(1)What(什么是互斥锁)(2)Why(互斥锁的用途)(3)How(如何使用互斥锁)(4)代码实践2、读写锁(1)What(什么是读写锁)(2)Why(读写锁的作用)(3)How(如何使用读写锁)(4)读写锁的特征3、条件变量(1)What(什么是条件变量)(2)Why(条件变量的作用)(3)How(如何使用条件变量实现线程......
  • 多线程复习总结
     1基本概念1什么是进程什么是线程进程:是程序执行一次的过程,他是动态的概念,是资源分配的基本单位。一个应用程序(1个进程是一个软件)。线程:一个进程可以有多个线程,线程是cpu调度的单位,一个进程中的执行场景/执行单元。对于java程序来说,当在DOS命令窗口中输入:javaHelloWorld回......