Java之多线程

发布时间:2023年12月18日

1.Java中实现多线程的方式

(1)继承Thread类

/**
* 注:
* 1.需要覆写Thread类中的run()方法
* 2.启动线程要依靠Thread类中的start()方法,线程启动后会默认调用run()方法
*/
public class MyThread extends Thread{
	private String title;
	
    public MyThread(String title){
        this.title=title;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
    
    @Override
    public void run(){
        System.out.println(this.title+"继承Thread类实现多线程");
    }
    }
    public class Main {
    public static void main (String[] args){
        MyThread t1 = new MyThread("线程1");
        MyThread t2 = new MyThread("线程2");
        MyThread t3 = new MyThread("线程3");
        t1.start();
        t2.start();
        t3.start();
    }
}

(2)实现Runnable接口

/**
* 注:
* 1.实现了Runnable接口的类将不再提供start()方法,所以为了继续使用Thread类启动多线程,可以利用Thread类中的构造方法对线程对象进行包裹
* 2.Thread类也是Runnable接口的子类。Thread类负责资源调度,实现Runnable的类负责处理真实业务
*/
public class MyThreadRunnable implements Runnable {
    private String title;
    
    public MyThreadRunnable(String title){
        this.title=title;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
    @Override
    public void run(){
        System.out.println("实现Runnable实现的多线程:"+this.title);
    }
}
public class Main {
    public static void main (String[] args){
        MyThreadRunnable t1 = new MyThreadRunnable("线程1");
        Thread thread1 = new Thread(t1);
        MyThreadRunnable t2 = new MyThreadRunnable("线程2");
        Thread thread2 = new Thread(t2);
        MyThreadRunnable t3 = new MyThreadRunnable("线程3");
        Thread thread3 = new Thread(t3);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

(3)实现Callable接口
Java针对多线程执行完毕后不能返回信息的缺陷,提供了Callable接口

/**
* 注:
* 1.需要通过java.util.concurrent.FutureTask类实现Callable接口与Thread类之间的联系
* 2.Callable接口泛型的值为call()方法的返回值类型
*/
public class MyThreadCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println("实现Callabe接口的多线程");
        return "返回值";
    }
}
public class Main {
    public static void main (String[] args){
        MyThreadCallable t1 = new MyThreadCallable();
        FutureTask<String> task1 = new FutureTask<>(t1);
        Thread thread1 = new Thread(task1);
        thread1.start();
    }
}

2.多线程的运行状态

在这里插入图片描述

(1)创建态
线程已经有了相应的内存空间和其他资源,但是处于不可运行的状态
对应语句:Thread 现成对象 = new Thread();

(2)就绪态
线程已经有了除了CPU的一切所需资源,在就绪队列中等待运行
对应语句:调用start()方法后,线程时处于就绪态

(3)运行态
线程在CPU上运行
对应语句:调用run()方法后,线程处于运行态

(4)阻塞态
一个正在运行的线程在某些特殊的情况下,将让出CPU并暂时中止自己的运行,进入阻塞状态
对应语句:如调用sleep()、suspend()、wait()等方法

(5)终止状态
当线程体中的run方法运行结束后,线程即处于终止状态,处于终止状态的线程不具有继续运行的能力

3.多线程常用的操作方法

(1)多线程的命名和取得
注:如果没有设置线程名称,系统会自动为其分配一个名称,名称的形式以“Thread-xxx”的方式出现

  • public Thread(Runnable target,String name)
    实例化线程对象,接收Runnable接口子类对象,同时设置线程名称
  • piblic final void setName(String name)
    设置线程名字
  • public final String getName()
    获取线程名字

(2)线程休眠
注:在进行休眠的时候有可能会产生中断异常InterruptedException,程序中必须强制性进行该异常的捕获与处理

  • public static void sleep(long millis)
    设置线程休眠的毫秒数,时间一到自动唤醒
  • public static void sleep(long millis,int nanos)
    设置线程休眠的毫秒数与纳秒数,时间一到自动唤醒

(3)线程中断
注:线程的中断是被动完成的,每当被中断执行后就会产生InterruptedException异常

  • public boolean isInterrupted()
    判断线程是否被中断
  • public void interrupt()
    中断线程执行

(4)线程强制执行

  • public final void join()
    设置线程为强制执行,待其执行完毕后其他线程再继续执行

(5)线程礼让

  • public static void yield()
    当满足某些条件时,可以将当前的调度让给其他线程执行

4.线程优先级

在Java的线程操作中,所有的线程在运行前都会保持在就绪状态,那么此时会根据线程的优先级进行资源调度

  • public static final int MAX_PRIORITY
    最高优先级,数值为10
  • public static final int NORM_PRIORITY
    中等优先级,数值为5
  • public static final int MIN_PRIORITY
    最低优先级,数值为1
  • public final void setPriority(int newPriority)
    设置线程优先级
  • public final int getPriority()
    取得线程优先级

5.线程同步

线程同步是指若干个线程对象并行进行资源访问时实现的资源处理的保护操作

(1)同步代码块实现线程同步
同步代码块指使用 synchronized关键字定义的代码块,在该代码块执行时往往需要设置一个同步对象,由于线程操作的不确定状态,所以这个时候的同步对象可以选择this

public class Ticket implements Runnable{
    //总票数10
    private  int ticket = 10;

    @Override
    public void run() {
        while(true){
        	//同步代码块
            synchronized (this){
                if(this.ticket > 0){
                    try{
                        //模拟网络延迟
                        Thread.sleep(50);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "卖票,ticket=" + this.ticket--);
                }else{
                    System.out.println("票已经卖光了");
                    break;
                }
            }
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        new Thread(ticket,"线程1").start();
        new Thread(ticket,"线程2").start();
        new Thread(ticket,"线程3").start();
    }
}

(2)同步方法实现线程同步
同步代码块可以直接定义在某个方法中,使得方法中的操作进行同步处理,在方法声明上使用synchronized关键字即可

6.后台守护线程

Java中的线程分为两类:用户线程和守护线程。守护线程是一种运行在后台的线程服务线程,当用户线程存在时,守护线程也可以同时存在,当用户线程全部消失时守护线程也会消失
注:用户线程和守护线程除了运行模式的区别外,其他完全相同

  • public final void setDaemon(boolean on)
    设置为守护线程
  • public final boolean isDaemon()
    判断是否为守护线程

7.volatile关键字

在多线程编程中,若干个线程为了可以实现公共资源的操作,往往是复制相应变量的副本,待操作完成后再将此副本变量数据与原始变量进行同步处理,如果需要直接进行原始变量操作可以在变量声明时使用volatile关键字

文章来源:https://blog.csdn.net/Lyhdreamer/article/details/129051682
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。