美文网首页
Java:多线程

Java:多线程

作者: iOS_修心 | 来源:发表于2023-05-24 23:53 被阅读0次

一、实现多线程

1、继承Thread类

方法名 说明
void run() 在线程开启后,此方法将被调用执行
void start() 使此线程开始执行,Java虚拟机会调用run方法()
  • run()方法和start()方法的区别?
    run():封装线程执行的代码,直接调用,相当于普通方法的调用
    start():启动线程;然后由JVM调用此线程的run()方法

  • 实现步骤

    • 定义一个类MyThread继承Thread类
    • 在MyThread类中重写run()方法
    • 创建MyThread类的对象
    • 启动线程
//实现多线程
 class MyThread extends Thread {
    @Override
    public void run() {
        // 当前线程
        String name = Thread.currentThread().getName();
        System.out.println(name);
        //代码就是线程在开启之后执行的代码
        for (int i = 0; i < 3; i++) {
            System.out.println("线程开启了" + i);
        }
    }
}
// 使用
public class Demo {
    public static void main(String[] args) {
        // 当前线程
        String name = Thread.currentThread().getName();
        System.out.println(name);

        //创建一个线程对象
        MyThread t1 = new MyThread();
      //表示的仅仅是创建对象,用对象去调用方法,并没有开启线程
        t1.run();
        //开启一条线程
        t1.start();
    }
}

2、实现Runnable接口

方法名 说明
Thread(Runnable target) 分配一个新的Thread对象
Thread(Runnable target, String name) 分配一个新的Thread对象
  • 实现步骤

    • 定义一个类MyRunnable实现Runnable接口
    • 在MyRunnable类中重写run()方法
    • 创建MyRunnable类的对象
    • 创建Thread类的对象,把MyRunnable对象作为构造方法的参数
    • 启动线程
// 实现Runnable接口
class MyRunnable implements Runnable{
    @Override
    public void run() {
        // 当前线程
        String name = Thread.currentThread().getName();
        System.out.println(name);

        //线程启动后执行的代码
        for (int i = 0; i < 3; i++) {
            System.out.println( "Runnable:" + i);
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        // 当前线程
        String name = Thread.currentThread().getName();
        System.out.println(name);

        //创建了一个参数的对象
        MyRunnable mr = new MyRunnable();
        //创建了一个线程对象,并把参数传递给这个线程.
        //在线程启动之后,执行的就是参数里面的run方法
        Thread t1 = new Thread(mr);
        //开启线程
        t1.start();
    }
}

3.实现Callable接口

方法名 说明
V call() 计算结果,如果无法计算结果,则抛出一个异常
FutureTask(Callable<V> callable) 创建一个 FutureTask,一旦运行就执行给定的 Callable
V get() 如有必要,等待计算完成,然后获取其结果
  • 实现步骤

    • 定义一个类MyCallable实现Callable接口
    • 在MyCallable类中重写call()方法
    • 创建MyCallable类的对象
    • 创建Future的实现类FutureTask对象,把MyCallable对象作为构造方法的参数
    • 创建Thread类的对象,把FutureTask对象作为构造方法的参数
    • 启动线程
    • 再调用get方法,就可以获取线程结束之后的结果。
/ 实现Callable接口
class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        // 当前线程
        String name = Thread.currentThread().getName();
        System.out.println(name);

        for (int i = 0; i < 3; i++) {
            System.out.println("Callable:" + i);
        }
        //返回值就表示线程运行完毕之后的结果
        return "答应";
    }
}
public class Demo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 当前线程
        String name = Thread.currentThread().getName();
        System.out.println(name);

        //线程开启之后需要执行里面的call方法
        MyCallable mc = new MyCallable();
        //可以获取线程执行完毕之后的结果.也可以作为参数传递给Thread对象
        FutureTask<String> ft = new FutureTask<>(mc);

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

        String s = ft.get();
        System.out.println(s);
    }
}

4.三种实现方式的对比

  • 实现Runnable、Callable接口
    • 好处: 扩展性强,实现该接口的同时还可以继承其他的类
    • 缺点: 编程相对复杂,不能直接使用Thread类中的方法
  • 继承Thread类
    • 好处: 编程比较简单,可以直接使用Thread类中的方法
    • 缺点: 可以扩展性较差,不能再继承其他的类

二、多线程的使用

1.设置和获取线程名称

方法名 说明
void setName(String name) 将此线程的名称更改为等于参数name
String getName() 返回此线程的名称
Thread currentThread() 返回对当前正在执行的线程对象的引用
static void sleep(long millis) 使当前正在执行的线程停留(暂停执行)指定的毫秒数
final int getPriority() 返回此线程的优先级
final void setPriority(int newPriority) 更改此线程的优先级线程默认优先级是5;线程优先级的范围是:1-10
void setDaemon(boolean on) 将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 30; i++) {
            try {
                // 不同线程睡眠时间不同,观察控制台打印
                String name = Thread.currentThread().getName();
                if (name.equals("1")){
                    Thread.sleep(10);
                }else{
                    Thread.sleep(20);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "---" + i);
        }
    }
}

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        MyRunnable mr = new MyRunnable();

        //线程是有默认名字的,格式:Thread-编号
        // 设置线程名
        Thread t1 = new Thread(mr,"1");
        Thread t2 = new Thread(mr,"2");
      
  //设置优先级: 1 - 10 默认值:5
        t1.setPriority(10);
        t2.setPriority(1);
        
        t1.start();
        t2.start();
    }
}

2.线程锁:synchronized

  • 安全问题出现的条件
    • 是多线程环境
    • 有共享数据
    • 有多条语句操作共享数据
  • 同步代码块格式:
  synchronized(任意对象) { 
    多条语句操作共享数据的代码 
  }

synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁


public class MyThread extends Thread {
    private static int ticketCount = 100;
    private static Object obj = new Object();

    @Override
    public void run() {
        while(true){
            synchronized (obj){ //就是当前的线程对象.
                if(ticketCount <= 0){
                    //卖完了
                    break;
                }else{
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    ticketCount--;
                    System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + ticketCount + "张票");
                }
            }
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();

        t1.setName("窗口一");
        t2.setName("窗口二");

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

2.线程锁:ReentrantLock

方法名 说明
ReentrantLock() 创建一个ReentrantLock的实例
  • 加锁解锁方法

    方法名 说明
    void lock() 获得锁
    void unlock() 释放锁
public class Ticket implements Runnable {
    //票的数量
    private int ticket = 100;
    private Object obj = new Object();
    private ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            lock.lock();
            if (ticket <= 0) {
                //卖完了
                break;
            } else {
                ticket--;
                System.out.println(Thread.currentThread().getName() + "在卖票,还剩下" + ticket + "张票");
            }
            lock.unlock();

        }
    }
}
public class Demo {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();

        Thread t1 = new Thread(ticket);
        Thread t2 = new Thread(ticket);
        Thread t3 = new Thread(ticket);

        t1.setName("窗口一");
        t2.setName("窗口二");
        t3.setName("窗口三");

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

3..生产者消费者

  • Object类的等待和唤醒方法

    方法名 说明
    void wait() 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法
    void notify() 唤醒正在等待对象监视器的单个线程
    void notifyAll() 唤醒正在等待对象监视器的所有线程

相关文章

  • 带你搞懂Java多线程(五)

    带你搞懂Java多线程(一)带你搞懂Java多线程(二)带你搞懂Java多线程(三)带你搞懂Java多线程(四) ...

  • 带你搞懂Java多线程(六)

    带你搞懂Java多线程(一)带你搞懂Java多线程(二)带你搞懂Java多线程(三)带你搞懂Java多线程(四)带...

  • Java多线程目录

    Java多线程目录 Java多线程1 线程基础Java多线程2 多个线程之间共享数据Java多线程3 原子性操作类...

  • java多线程--Callable

    **移步[java多线程系列文章]Java多线程(二十二)---LockSupport工具Java 停止线程 一、...

  • android 多线程 — 线程的面试题和答案

    这里都是我从各个地方找来的资料,鸣谢: Java多线程干货系列—(一)Java多线程基础 JAVA多线程和并发基础...

  • 5月份第一周学习安排

    学习内容: java多线程及线程同步的方法(使用) java多线程各种同步方法的原理和优缺点 java多线程设计模...

  • 带你搞懂Java多线程(四)

    带你搞懂Java多线程(一)带你搞懂Java多线程(二)带你搞懂Java多线程(三) 什么是线程间的协作 线程之间...

  • Java基础(六)

    多线程 Java多线程并发 1.1 JAVA 并发知识库 1.2 JAVA 线程实现/创建方式 1.2.1 继承 ...

  • (五) volatile关键字

    Java多线程目录 1 背景 理解Java多线程的内存抽象逻辑请阅读java多线程内存模型,当代操作系统,处理器为...

  • Java多线程高级特性(JDK8)

    [TOC] 一、Java多线程 1.Java多线程基础知识 Java 给多线程编程提供了内置的支持。一条线程指的是...

网友评论

      本文标题:Java:多线程

      本文链接:https://www.haomeiwen.com/subject/mkpjsdtx.html