Java多线程笔记

本文详细介绍了Java中的线程概念,包括睡眠、挂起、阻塞和等待的区别,以及Runnable接口、Callable接口的使用。重点讨论了如何通过继承Thread类、实现Runnable接口和Callable接口创建线程,以及同步代码块、同步方法和死锁的示例。
摘要由CSDN通过智能技术生成

睡眠和挂起是用来描述行为,而阻塞和等待用来描述状态。

阻塞和等待的区别在于,阻塞是被动的,它是在等待获取一个排它锁。而等待是主动的,通过调用 Thread.sleep() 和 Object.wait() 等方法进入。

死亡(Terminated)

可以是线程结束任务之后自己结束,或者产生了异常而结束。

线程使用方式


有三种使用线程的方法:最新面试资料宝典

  • 实现 Runnable 接口;

  • 实现 Callable 接口;

  • 继承 Thread 类。

实现 Runnable 和 Callable 接口的类只能当做一个可以在线程中运行的任务,不是真正意义上的线程,因此最后还需要通过 Thread 来调用。可以说任务是通过线程驱动从而执行的。

继承 Thread 类

public class ThreadTest {

/**

  • 多线程的创建,

  • 方式一:

  • 1.继承与Thread类

  • 2.重写Thread类的run方法->将此线程执行的操作声明在run中

  • 3.创建Thread类的子类

  • 4.通过此对象调用start

*/

public static void main(String[] args) {

// 创建Thread类的子类的对象

MyThread t1 = new MyThread();

//不能通过run方法开启线程,因为还会在主线程中运行,应该使用start方法开启线程

//不能通过调用两次start方法来开启两个子线程

t1.start();

//可以通过再创建一个对象来实现

for (int i=0;i<1000;i++){

if (i%2!=0){

System.out.println(i+“****”);

}

}

}

}

class MyThread extends Thread{

@Override

public void run() {

for (int i=0;i<1000;i++){

if (i%2==0){

System.out.println(i);

}

}

}

}

/**

  • 方式二:

  • 匿名子类创建,针对只调用一次的线程

*/

public static void main(String[] args) {

MyThread1 myThread1 = new MyThread1();

myThread1.start();

MyThread2 myThread2 = new MyThread2();

myThread2.start();

//通过匿名子类实现调用:特点只需要调用一次的子线程

new Thread(){

@Override

public void run() {

for (int i=0;i<1000;i++){

if (i%3==0){

System.out.println(Thread.currentThread().getName()+“***”+i);

}

}

}

}.start();

}

}

class MyThread1 extends Thread{

@Override

public void run() {

for (int i=0;i<100;i++){

if (i%2!=0){

System.out.println(Thread.currentThread().getName()+“***”+i);

}

}

}

}

class MyThread2 extends Thread{

@Override

public void run() {

for (int i=0;i<100;i++){

if (i%2==0){

System.out.println(Thread.currentThread().getName()+“***”+i);

}

}

}

}

###实现 Runnable 接口

package com.atguigu.juc.runnable;

/**

  • 创建多线程方式Runnable

  • 1.创建一个实现Runnable接口的类

  • 2.实现类去实现Runnable中的抽象方法: run( )

  • 3.创建实现类的对象

  • 4、将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象

  • 5,通过Thread类的对象调用start()

*/

public class TestThread {

public static void main(String[] args) {

//3.创建实现类的对象

MyThread myThread = new MyThread();

//4、将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象

Thread t1 = new Thread(myThread);

//5,通过Thread类的对象调用start()

t1.start();

}

}

//1.创建一个实现Runnable接口的类

class MyThread implements Runnable{

//2.实现类去实现Runnable中的抽象方法: run( )

@Override

public void run() {

for (int i=0;i<100;i++){

if (i%2==0){

System.out.println(i);

}

}

}

}

实现 Callable 接口


线程常见方法

package com.atguigu.juc.tset01;

/**

  • 1.yield():释放当前cpu的执行权

  • 2.start():启动当前线程;调用当前线程的run()

  • 3.run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中

  • 4.getName()∶获取当前线程的名字

  • 5.setName():设置当前线程的名字

  • 6.currentThread():静态方法,返回执行当前代码的线程

  • 7.join():在线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行完以后,线程a才结束阻塞状态。

  • 8.sleep():让当前线程"睡眠”指定的毫秒。在指定的毫秒时间内,当前线程是阻塞状态。

*/

public class MyThreatTest {

public static void main(String[] args) {

TestMyThread t1 = new TestMyThread();

t1.start();

new Thread(){

@Override

public void run(){

for (int i=0;i<100;i++){

if (i%2==0){

try {

sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + “子线程” + i);

yield();

}

}

}

}.start();

for (int i=0;i<100;i++){

if (i%3==0){

System.out.println(Thread.currentThread().getName() + “main方法” + i);

}

if (i==20){

try {

t1.join();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

class TestMyThread extends Thread{

@Override

public void run(){

for (int i=0;i<100;i++){

if (i%5==0){

System.out.println(Thread.currentThread().getName() + “2222222222222子线程” + i);

}

}

}

}

synchronized锁机制

一把锁只能同时被一个线程获取,没有获得锁的线程只能等待;

每个实例都对应有自己的一把锁(this),不同实例之间互不影响;例外:锁对象是*.class以及synchronized修饰的是static方法的时候,所有对象公用同一把锁

synchronized修饰的方法,无论方法正常执行完毕还是抛出异常,都会释放锁

##同步代码—Runnable接口方式

/**

*方式一:同步代码块

  • synchronized(同步监视器){

  •      //需要被同步的代码
    
  • }

  • 说明:

  • 1.操作共享数据的代码,即为需要被同步的代码

  • 2.共享数据:多个线程共同操作的变量

  • 3.同步监视器,俗称:锁。任何一个类的对象都可以作为索

  • 4.在Java中,我们通过同步机制,来解决线程的安全问题。

  • 补充:在实现Runnable接口创建多线程的方式中,我们可以考虑使用this充当同步监视器。

  • 方式二:同步方法

  • 如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明同步的。

  • 5.同步的方式,解决了线程的安全问题。—好处

  • 操作同步代码时,只能有一个线程参与,其他线程等待。相当于是一个单线程的过程,效率低。

*/

public class WindowToRunnable {

public static void main(String[] args) {

Window2 window2 = new Window2();

Thread t1 = new Thread(window2);

Thread t2 = new Thread(window2);

Thread t3 = new Thread(window2);

t1.setName(“窗口1”);

t2.setName(“窗口2”);

t3.setName(“窗口3”);

t1.start();

t2.start();

t3.start();

}

}

class Window2 implements Runnable{

//这里不用加static,因为调用的对象只有一个

private int ticket=100;

@Override

public void run() {

while (true) {

synchronized (this.getClass()){

if (ticket > 0) {

// try {

// Thread.sleep(100);

// } catch (InterruptedException e) {

// e.printStackTrace();

// }

System.out.println(Thread.currentThread().getName() + “买票,票号:” + ticket);

ticket–;

}

}

}

}

}

同步方法–Runnable接口方法


package com.atguigu.juc.bookPage;

/**

  • 使用同步方法解决实现Runnable接口的线程安全问题

  • 关于同步方法的总结:

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

  • 2.非静态的同步方法,同步监视器是: this

  • 静态的同步方法,同步监视器是:当前类本身

*/

public class WindowExtSynn {

public static void main(String[] args) {

Window4 w1 = new Window4();

Window4 w2 = new Window4();

Window4 w3 = new Window4();

w1.setName(“窗口1”);

w2.setName(“窗口2”);

w3.setName(“窗口3”);

w1.start();

w2.start();

w3.start();

}

}

class Window4 extends Thread{

private static int ticket=100;

@Override

public void run() {

while (true){

show();

}

}

private static synchronized void show() {

if (ticket>0){

System.out.println(Thread.currentThread().getName()+“:买票:票号为”+ticket);

ticket–;

}

}

}

##同步方法—继承方法

package com.atguigu.juc.bookPage;

/**

  • 使用同步方法解决实现Runnable接口的线程安全问题

  • 关于同步方法的总结:

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

  • 2.非静态的同步方法,同步监视器是: this

  • 静态的同步方法,同步监视器是:当前类本身

*/

public class WindowExtSynn {

public static void main(String[] args) {

Window4 w1 = new Window4();

Window4 w2 = new Window4();

Window4 w3 = new Window4();

w1.setName(“窗口1”);

w2.setName(“窗口2”);

w3.setName(“窗口3”);

w1.start();

w2.start();

w3.start();

}

}

class Window4 extends Thread{

private static int ticket=100;

@Override

public void run() {

while (true){

show();

}

}

private static synchronized void show() {

if (ticket>0){

System.out.println(Thread.currentThread().getName()+“:买票:票号为”+ticket);

ticket–;

}

}

}

##死锁

示例:两个线程都拿到第一层锁的key,然后都需要第二层锁的key,但key在对方手中,而方法没有执行完,都不可能释放key,互相僵持。

import static java.lang.Thread.sleep;

public class TestSyn {

public static void main(String[] args) {

StringBuffer s1 = new StringBuffer();

StringBuffer s2 = new StringBuffer();

new Thread(){

@Override

public void run() {

synchronized (s1) {

s1.append(“a”);

s2.append(“1”);

try {

sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (s2) {

s1.append(“b”);

s2.append(“2”);

System.out.println(s1);

System.out.println(s2);

}

}

}

}.start();

new Thread(new Runnable() {

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (s2) {

s1.append(“b”);

s2.append(“2”);

System.out.println(s1);

System.out.println(s2);

}

}

}

}.start();

new Thread(new Runnable() {

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-0vAn5oxx-1714824333728)]

[外链图片转存中…(img-4T6MMXBF-1714824333729)]

[外链图片转存中…(img-RbWRWmC7-1714824333729)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 26
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值