首页 > 其他分享 >多线程

多线程

时间:2022-09-07 00:00:07浏览次数:79  
标签:java Thread list 线程 new 多线程 public

多线程

概念

  • 同步

    先做1,1做完了再做2

  • 异步

    两件事可以一起做

    • 并行

      在一个CPU核心上只运行一件事

    • 并发

      在一个CPU核心上运行多件事,利用CPU时间切片技术

      • 多进程

        进程与进程之间,内存不共享 运行一个应用程序,就是启动了一个进程,这个刚刚启动的进程,叫做主进程 由主进程创建的进程,叫做子进程

      • 多线程

        线程与线程之间,内存共享(方法区和堆区共享) 只要有进程,每个进程里面,都默认有一个线程,此线程叫做主线程 由主线程创建的线程,叫做子线程

      • 多协程

快速入门

  • Thread.sleep()

    在当前线程睡眠,单位为毫秒

  • Thread::start

    启动线程

  • Thread::run

    线程在执行时,要运行的代码

  • SecondThread.java

package com.futureweaver.multithread;

public class SecondThread extends Thread {
@Override
public void run() {
try {
while (true) {
System.out.println("第二个线程的代码");
Thread.sleep(1500);
}
} catch (InterruptedException e) {
System.out.println("第二个线程退出了...");
}
}
}

  • ThreadPractice.java
package com.futureweaver.multithread;

public class ThreadPractice {
public static void main(String[] args) throws InterruptedException {
Thread thread = new SecondThread();
thread.start();

    while (true) {
        System.out.println("主线程里面的代码");

        // InterruptedException异常为别人想要关闭此线程
        // 在运行此代码时,会收到一个异常
        // 抓此异常,目的是为了释放掉自己所占用的资源
        // 抛此异常,目的是不做任何处理,直接退出程序

        // 当前线程睡眠多少毫秒
        Thread.sleep(2000);
    }
}

}

使用时的注意事项

每创建一个线程,都要有名字

Thread结合Runnable的用法

在使用线程时,应注意关注点分离,Thread只用于处理创建线程、在线程里执行过程等等的功能 Runnable只关注要干什么 关注点分离的好处在于,无需重度重写父类的方法,就可以直接用

  • SecondRunnable.java
package com.futureweaver.multithread;

public class SecondRunnable implements Runnable {
@Override
public void run() {
try {
while (true) {
System.out.println("这是一个Thread结合Runnable要执行的代码");
Thread.sleep(1500);
}
} catch (InterruptedException e) {
System.out.println("线程退出...");
}
}
}

  • Thread2Practice.java
package com.futureweaver.multithread;

// 多线程的第二种用法
// Thread结合Runnable使用

public class Thread2Practice {
public static void main(String[] args) throws InterruptedException {
SecondRunnable secondRunnable = new SecondRunnable();
Thread thread = new Thread(secondRunnable, "thread and runnable ...");
thread.start();

    while (true) {
        System.out.println("主线程代码");

        Thread.sleep(2000);
    }
}

}

Runnable的匿名内部类的用法

  • Thread2Practice.java
package com.futureweaver.multithread;

// 多线程的第二种用法
// Thread结合Runnable使用

public class Thread2Practice {
public static void main(String[] args) throws InterruptedException {
Runnable secondRunnable = new Runnable() {
@Override
public void run() {
try {
while (true) {
System.out.println("second runnable里的过程");
Thread.sleep(1500);
}
} catch (InterruptedException e) {
System.out.println("线程退出了");
}
}
};
Thread thread = new Thread(secondRunnable, "thread and runnable ...");
thread.start();

    while (true) {
        System.out.println("主线程代码");

        Thread.sleep(2000);
    }
}

}

Runnable的lambda表达式写法【重点】

  • Thread2Practice.java
package com.futureweaver.multithread;

// 多线程的第二种用法
// Thread结合Runnable使用

public class Thread2Practice {
public static void main(String[] args) throws InterruptedException {
// 匿名内部类,缺什么方法,就重写什么方法即可
// lambda表达式必须是函数式接口

    // public void run() {...}
    // public是能够智能识别的
    // void是能够智能识别
    // ()说明的是函数式接口当中的函数没有任何参数,假设有参数,参数类型都不用写,因为可以智能识别
    // ->用于分隔参数和函数体/方法体
    // {}方法体
    // 方法体内,如果函数式接口当中的函数需要返回值,那就写return语句
    // 如果返回值类型为void,那就不写return语写
    Thread thread = new Thread(() -> {
        try {
            while (true) {
                System.out.println("second runnable里的过程");
                Thread.sleep(1500);
            }
        } catch (InterruptedException e) {
            System.out.println("线程退出了");
        }
    }, "thread and runnable ...");
    thread.start();

    while (true) {
        System.out.println("主线程代码");

        Thread.sleep(2000);
    }
}

}

注意

  1. 主线程退出,其他线程不管有没有执行结束,都会结束
  2. 当多个线程同时使用一个资源时,极有可能会出现线程同步问题: 当多个线程同时争抢一个资源时,操作此资源的代码如果无法保证原子性(类似于数据库中的事务),就会产生数据错乱问题 为了保证数据是对的,或保证数据的一致性,需要在操作此资源时添加线程同步的机制 推荐使用synchronized关键字来保证此机制

线程同步操作演示

  • SecondRunnable.java
package com.futureweaver.threadsync;

import java.util.ArrayList;
import java.util.List;

public class SecondRunnable implements Runnable {
private List<String> list;

public SecondRunnable(List&lt;String&gt; list) {
    this.list = list;
}

@Override
public void run() {
    try {
        for (int i = 20000; i &lt; 21000; i++) {
            Thread.sleep(1);
            add(list, Integer.toString(i));
        }
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
}

// syncrhonized关键字能够保证在操作此list时,不会发生资源争抢问题
public static synchronized void add(List&lt;String&gt; list, String str) {
    // 开始
    list.add(str);
    // 结束
}

}

  • ThreadPractice.java
package com.futureweaver.threadsync;

import java.util.ArrayList;
import java.util.List;

public class ThreadPractice {
public static void main(String[] args) throws InterruptedException {
List<String> list = new ArrayList<>();
SecondRunnable secondRunnable = new SecondRunnable(list);
Thread thread = new Thread(secondRunnable);
thread.start();

    for (int i = 0; i &lt; 10000; i++) {
        Thread.sleep(1);
        String s = Integer.toString(i);
        SecondRunnable.add(list, s);
    }

    Thread.sleep(5000);
    System.out.println(list);
}

}

死锁问题

所谓死锁问题,就是在等待一把永远也解不开的锁

死锁案例1

加锁后出现异常,导致锁无法解开

  • SecondRunnable.java
package com.futureweaver.threadsync;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SecondRunnable implements Runnable {
private List<String> list;

// 注意,如果多个线程同时操作某个资源
// 那么想要用Lock加线程同步,必须要保证这几个线程用的是同一把锁
public static Lock lock = new ReentrantLock();

public SecondRunnable(List&lt;String&gt; list) {
    this.list = list;
}

@Override
public void run() {
    try {
        for (int i = 20000; i &lt; 21000; i++) {
            Thread.sleep(1);
            add(list, Integer.toString(i));
        }
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
}

public static void add(List&lt;String&gt; list, String str) {
    // 将这一把锁上锁
    lock.lock();

    // 开始
    list.add(str);
    // 结束

    list.get(30000);

    // 将这一把锁解锁
    lock.unlock();
}

}

  • ThreadPractice.java
package com.futureweaver.threadsync;

import java.util.ArrayList;
import java.util.List;

public class ThreadPractice {
public static void main(String[] args) throws InterruptedException {
List<String> list = new ArrayList<>();
SecondRunnable secondRunnable = new SecondRunnable(list);
Thread thread = new Thread(secondRunnable);
thread.start();

    for (int i = 0; i &lt; 10000; i++) {
        Thread.sleep(1);
        String s = Integer.toString(i);
        SecondRunnable.add(list, s);
    }

    Thread.sleep(5000);
    System.out.println(list);
}

}

死锁案例二

小明锁了A,等待B。同时B被小红锁上,等待A

  • XiaoHong.java
package com.futureweaver.threadsync;

import java.util.concurrent.locks.Lock;

public class XiaoHong implements Runnable {
private Lock left;
private Lock right;

public XiaoHong(Lock left, Lock right) {
    this.left = left;
    this.right = right;
}

@Override
public void run() {
    right.lock();
    System.out.println("小红拿到第二根筷子");

    left.lock();
    System.out.println("小红拿到第一根筷子");

    System.out.println("吃饭");

    left.unlock();
    right.unlock();
}

}

  • XiaoMing.java
package com.futureweaver.threadsync;

import java.util.concurrent.locks.Lock;

public class XiaoMing implements Runnable {
private Lock left;
private Lock right;

public XiaoMing(Lock left, Lock right) {
    this.left = left;
    this.right = right;
}

@Override
public void run() {
    left.lock();
    System.out.println("小明拿到了第一根筷子");

    right.lock();
    System.out.println("小明拿到了第二根筷子");

    System.out.println("吃饭");

    right.unlock();
    left.unlock();
}

}

  • DoubleLockDeadPractice.java
package com.futureweaver.threadsync;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class DoubleLockDeadPractice {
public static void main(String[] args) {
Lock left = new ReentrantLock();
Lock right = new ReentrantLock();

    Thread xiaohong = new Thread(new XiaoHong(left, right));
    Thread xiaoming = new Thread(new XiaoMing(left, right));

    xiaohong.start();
    xiaoming.start();
}

}

标签:java,Thread,list,线程,new,多线程,public
From: https://www.cnblogs.com/futureweaver/p/16663790.html

相关文章

  • 多线程---实现Callable接口
    实现Callable接口  案例:packagecom.mokuiran.thread;​importorg.apache.commons.io.FileUtils;​importjava.io.File;importjava.io.IOException;importjava.......
  • 多线程---Lamba表达式
    Lambda表达式参考视频:多线程10:Lamda表达式哔哩哔哩bilibili  理解函数式接口是学习java8lambda表达式的关键所在函数式接口的定义:任何接口,如果只包含唯一一个......
  • 多进程和多线程结合跑满cpu
    importjsonimportmultiprocessingimportthreadingimporttimeimportrandomimportrequestsimporturllib3lock=threading.RLock()urllib3.disable_warning......
  • java随笔(七)——多线程(比较详细)
    线程线程是进程中单个的顺序控制流,是一条执行路径单线程:一个进程如果只有一条执行路径,则称为单线程程序多线程:一个进程如果有多条执行路径,则称为多线程程序多线程的实......
  • Java多线程相关概念
    Java多线程相关概念1.并发是在同一实体上的多个事件,是在同一台处理器上“同时”处理多个任务,同一时刻,其实是只有一个事件在发生2.并行是在不同实体上的多个事件,是在......
  • 多线程---Thread和Runnable
    多线程参考视频:多线程02:线程、进程、多线程哔哩哔哩bilibili1.概念     2.线程创建创建线程方式一:继承Thread类,重写run()方法,调用start开启线程packagec......
  • 比较:java多线程 sleep()和wait()
    相信看这篇文章的朋友都已经知道进程和线程的区别,也都知道了为什么要使用多线程了。这两个方法主要来源是,sleep用于线程控制,而wait用于线程间的通信,与wait配套的......
  • 内部类-多线程-静态代理
    内部类概念:一个类中定义另外一个类,那这个另外的类就是内部类分类:在类的成员位置:成员内部类(如果内部类被static修饰,则这个内部类称之为静态内部类)在......
  • 3.多线程开发
    线程的常用方法:- t.start(),当前线程准备就绪(等待CPU调度,具体时间由CPU进行决定)   -t.join(),等待当前线程的任务执行完毕后再向下继续执行。i......
  • 并发多线程11std::atomic续谈、std::async深入谈
    std::atomic续谈、std::async深入谈一、std::atomic续谈#include<iostream>#include<thread>#include<atomic>usingnamespacestd;std::atomic<int>g_count=......