JAVA 多线程

目录

多线程

进程与线程

(1)新建状态(new Thread)

(2)就绪状态( Runnable )

(3)运行状态(Running)

(4)不可运行状态(non Runnable)

(5)终止状态(Dead)

(6)转换方法

创建多线程的两种方法

继承Thread类

实现Runable接口

多线程共享资源例子

线程基本控制方法

线程互斥与同步

多线程同步


相关内容:JAVA 基本知识 JAVA 类和对象 JAVA 类的特性 JAVA 文件读写

多线程

介绍什么是多线程,创建多线程的两种方法

线程同步与互斥,后台线程。

进程与线程

  • 程序是计算机指令的集合,而进程就是一个运行中的程序,它指的是从代码加载、执行到执行结束这样一个完整的过程。每个进程都是占用不同的内存空间
  • 而线程(Thread)则是进程中某个单一顺序的控制流,也被称为轻量进程,它被操作系统调度,并在处理器或内核上运行。
  • 一个进程都有一个主线程(primary thread),一个进程也可以由多个线程组成,每条线程并行执行不同的任务,这多个线程共享同一个内存空间。

(1)新建状态(new Thread)

Thread myThread = new MyThreadClass( );

  • 当⼀个线程处于新建状态时,它仅仅是⼀个空的线 程对象,系统不为它分配资源

(2)就绪状态( Runnable )

myThread.start( );

  • 当一个线程处于就绪状态时,系统为这个线程分配了它需的系统资源,安排其运行并调用线程运行方法,这样就使得该线程处于就绪( Runnable )状态。
  • 需要注意的是这一状态并不是运行状态(Running ),因为线程也许实际上并未真正运行。由于很多计算机都是单处理器的,所以要在同一时刻运行所有的处于可运行状态的线程是不可能的,Java的运行系统必须实现调度来保证这些线程共享处理器

(3)运行状态(Running)

  • 正在运行的线程处于运行状态,此时该线程独占CPU的控制权。如果有更高的优先级线程出现,则该线程将被迫放弃控制权进入可运行态。使用yield()方法可以使线程主动放弃CPU控制权。线程也可能由于执行结束或执行stop()方法放弃控制权进入终止状态。

(4)不可运行状态(non Runnable)

等待态、阻塞态、睡眠态

进入不可运行状态的原因有如下几条:

  • 调用了sleep()方法;
    • 如果线程调用sleep()方法进入了休眠状态,不能调用任何方法(interrupt)让它脱离阻塞状态,只能等待指定的时间之后,自动脱离阻塞态。

      线程睡眠到期自动苏醒,并返回到可运行状态(就绪),不是运行状态。

  • 调用了suspend()方法;
    • 如果一个线程调用suspend()方法被挂起 而进入了阻塞状态,必须在其他线程中调用resume()方 法。
  • 该线程正在等待I/O操作完成;
    • 如果线程由于等待I/O而进入了阻塞状态,只能等待这个 I/O操作完成之后,系统调用特定的指令来使该线程恢复可 运行状态。
  • 调用wait()方法;
    • 如果线程为了等待一个条件变量而调用了wait()方法进入了 阻塞态,需要这个条件变量所在的那个对象调用notify(()或 notifyAll()方法。
  • 输入输出流中发生线程阻塞。

(5)终止状态(Dead)

  • 线程的终止一般可通过两种方法实现:自然撤消(线程执行完)或是被停止(调用stop()方法)。线程一旦进 入终止状态就不再存在了,也无法改变为其它状态。目 前不推荐通过调用stop()来终止线程的执行,而是让线程执行完。

(6)转换方法

创建多线程的两种方法

继承Thread类

 class ThreadExample extends Thread{} 

创建Thread对象:

ThreadExample1 t1 = new ThreadExample1 ();
this.getname();

特点:

  • 不能再从其他类继承。
  • 编写简单,可以直接操纵线程,*无需使用Thread.currentThread()*(用于获得Thread类对象)

实现Runable接口

class RunableExample implements Runnable{}

创建Thread对象:

RunableExample1 r = new RunableExample1();
Thread t = new Thread(r); 

Thread.currentThread().getName()

特点:

  • 可以将代码和数据分开,形成清晰的模型

  • 还可以从其他类继承

  • 保持程序风格的一致

  • 共享一个目标对象,实现多个线程处理同一个资源

    多线程共享资源例子

    RunnableExample2 t1= new RunnableExample2();//创建线程类 
    Thread t1s = new Thread(t1); //创建线程 3个共享一个run();
    Thread t2s = new Thread(t1); 
    Thread t3s = new Thread(t1);
    

线程基本控制方法

都是Thread类的成员方法!首先要获得Thread类的某个对象。

  • public void start();//启动该线程,将导致run方法被自动调用。该方法将立即返回,新线程将运行

  • public void run();//必须覆盖该方法,在方法体中添加你想要在该线 程中执行的代码

  • public static void sleep(long millis) throws InterruptedException;//使当前正在执行的线程睡眠指定的时间

  • **public void interrupt()**;//用于将一个中断请求发送给线程

  • public static boolean interrupted();//用于测试当前线程(即正在执行该指令的线程)是否已经被中断

  • public boolean isInterrupted();//用于测试某个线程是否已经被中断

  • public final boolean isAlive();//用于测试某个线程是否还活着

  • public final void setPriority(int newPriority);//设置线程的优先级1-10 //不要假定高优先级的线程一定先于低优先级的线程执行,不要有逻辑依赖于线程优先级,否则可能产生意外结果

  • public final void join(long millis) throws InterruptedException;//使某个 线程等待指定的时间。调用某线程的该方法,将当前线程与该线程“ 合并”,即等待该线程结束,再恢复当前线程的运行。

  • public final int getPriority() ; //获得线程的优先级

  • public static Thread currentThread();返回代表当前正在执行的线程的 Thread对象

  • public static void yield() ;使当前正在执行的线程临时暂停,以使其它的线程运行

    线程让步,不一定成功

  • public final void wait(long timeout) throws InterruptedException;当前线程被中断,并进入到一个对象的等待列表中,直到另外的线程调用同一个对象上的notify() 或notifyAll() 方法

  • public final void notify() ;用于将对象等待列表中的任选的一个线程唤醒,使它再次成为可运行的线程

  • public final void notifyAll();用于将对象等待列表中的所有线程唤醒, 使它们再次成为可运行的线程

  1. 线程睡眠sleep(int)
    • 单位为ms
  2. 睡眠唤醒interrupt()
  3. 线程让步yield()
    • 这种让步并不一定每次都见效,在调度机制的影响下也有可能没有成功让步 。
  4. 线程等待join()
    • void join() 等待该线程终止。
    • void join(long millis) 等待该线程终止的时间最长为 millis 毫秒。
    • void join(long millis, int nanos) 等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒

线程互斥与同步

多线程同步

  • 为了确保在任何时刻一个共享对象只被一个线程使用,必须使用“同步(synchronized)”

  • 有两种方式实现同步:

       synchronized void methodA() { } //使用同步块 
       synchronized(obj){ //obj是被锁定的对象 //要同步的语句 }
    
  • 用synchronized来标识的块或方法即为监视器监视的部分。只有使用synchronized ,才能利用对象的监视器功能。

实现接口,共用一个类

public void run() {
        while (true) {
            synchronized (this) {
                if (ticket > 0) {
                    try {//为了演示,线程在这里睡眠一次 
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } //睡眠结束后,继续当前的票进行销售
                    System.out.println(Thread.currentThread().getName() + "卖票-->" + (this.ticket--));
                } else {
                    break;
                }
            }
        }
    }

继承Thread类的代码如何同步?

public void run() {
while(true){
  synchronized("123"){
    //函数体(要写break,判断退出)
    if(ticket<0) break; 
    System.out.println(this.getName()+ "卖票-->"+(this.ticket--));
    int ticketShell=ticket;
  }
  while(ticketShell==ticket){
    "123".notify();
    "123".waite();
  }
  sleep();
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值