ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

多线程

2022-09-07 00:00:12  阅读:169  来源: 互联网

标签: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
来源: https://www.cnblogs.com/futureweaver/p/16663790.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有