多线程
2021-06-07 03:04
标签:time write 提前 文件创建 下载器 f11 mss priority 生产者消费者模式 Java.Thread类 程序:指令和数据的有效集合,本身没有任何运行含有,是一个静态的概念 进程:执行程序的一次执行过程,是一个动态的概念。是系统资源分配的单位 线程:通常一个进程可以包含多个线程(由调度器安排调度,不可人为干预)一个进程至少有一个线程,线程是CPU调度和执行的单位 自定义线程类并继承Thread类 重写run()方法,编写线程执行体 创建线程对象,调用start()方法启动线程 启动方式:子类对象.start() 注:run()方法只有主线程一条执行路径,start()方法有多条执行路径,线程交替执行 定义线程类实现Runnable接口 实现run()方法,编写线程执行体 创建Thread线程对象,通过start()方法启动线程 启动方式:传入目标对象+Thread对象.start() 推荐使用此方式:可以避免单继承,灵活方便,方便一个对象被多个线程使用 λ是希腊字母表中排行第十一位的字母,英语名称位Lambda Lambda表达式的出现是为了简化繁琐的表达式,可以用于匿名内部类定义过多。属于函数式编程 函数式接口: 任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口 对于函数式接口,我们可以通过lambda表达式来创建该接口的对象 调度:操作系统给线程分配时间片(就绪状态进入运行状态的方式) 模拟网络延时可以放大问题发生的可能性 通过线程休眠实现每秒打印异常当前时间 Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞 通过Thread.getState()方法来观测线程状态 线程优先级高不一定先执行,只是先执行的概率会大大提高(给的资源多) Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度那个线程来执行 线程优先级的表示 用数字来表示,范围1~10 改变线程优先级的方法 并发:同一个对象被多个线程同时操作 现实生活中:我们遇到这种问题(食堂排队打饭)时,解决办法就是排队一个一个来 在处理多线程问题时,遇到这种并发情况,我们就需要线程同步。 线程同步:是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面的线程使用完毕,下一次才开始使用 这是线程同步的形成条件 每一个对象都有一把锁,可以实现线程安全 锁机制:synchronized排他锁,可以独占资源,而其他线程必须等待锁的释放 存在的问题: 默认锁this 锁的对象需要是Object类型的 相互等待对方锁定的资源:自己抱着一个锁去等另外一个锁。想要同时持有两个锁,但是都不想给 死锁的避免(四个必要条件) 上面这四个必要条件,只要想办法破解其中任意一个或多个就可以避免死锁的发生 注意:锁要写在并非线程类中 注意:要区分线程循环和方法循环的区别 Lock是显式锁,synchronized是隐式锁 Lock只有代码块锁,synchronized有代码块锁和方法锁 使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且有更好的拓展性 优先顺序 Lock > 同步代码块(已经进入了方法体,分配了相应资源) > 同步代码块(方法体之外) 自我总结: Lock可以显式的对不安全代码进行加锁和解锁,适合在run方法中写代码的情况 synchronized关键字是隐形的对this加锁,可以使得本类一次只能一个线程调用。关键字的位置很重要,适合在多线程类中写方法,在run中调用方法 生产者消费者模式(问题) Java中提供的几个解决线程通信的问题 注:以上方法都是Object类的方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常IllegalMonitorStateException。 通过缓冲区过度数据 Producer(生产者) 缓冲区 Consumer(消费者) 注意:一个文件中只能有一个public类 相当于是只有一个位置的缓冲区 注意标志位每次调用方法都要更改 从JDK5.0起提供了线程池相关的API:ExecutorService和Executors ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池 多线程 标签:time write 提前 文件创建 下载器 f11 mss priority 生产者消费者模式 原文地址:https://www.cnblogs.com/zhoushuaiyi/p/14591925.htmlprocess(进程)和Thread(线程)
1. 线程的创建
1. 通过继承Thread
package com.zhou3.Thread;
public class TestThreadDemo01 extends Thread{
@Override
public void run() {
//run方法线程体
for (int i = 0; i
2. 通过实现Runnable
package com.zhou3.Thread;
/*
多个线程同时操作同一个对象
没有对单一对象进行操作控制,存在并发问题
*/
public class TestThread implements Runnable{
private int ticketNumber = 10;
@Override
public void run() {
while (true){
if(ticketNumber
package com.zhou3.Thread;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/*
练习多线程,同步下载漂亮的图片
*/
public class TestThreadDemo02 implements Runnable{
//类属性
private String url;
private String name;
//有参构造函数
public TestThreadDemo02(String url,String name){
this.name = name;
this.url = url;
}
@Override
public void run() {
WebDownloader webDownloader = new WebDownloader();
webDownloader.downloader(url,name);
System.out.println(name + "已经下载");
}
}
//下载器
class WebDownloader{
public void downloader(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO异常,downloader方法出现问题");
}
}
//main线程实现 多线程对象执行
public static void main(String[] args) {
TestThreadDemo02 t1 = new TestThreadDemo02("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fattach.bbs.miui.com%2Fforum%2F201110%2F20%2F104212ds59m9rtqspt6tzt.jpg&refer=http%3A%2F%2Fattach.bbs.miui.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1618908610&t=8c2e3d5e4418b17dcdccf84593a7cfed","1.jpg");
TestThreadDemo02 t2 = new TestThreadDemo02("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2F1114%2F0H320120Z3%2F200H3120Z3-6-1200.jpg&refer=http%3A%2F%2Fpic.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1618908800&t=e7ef5c1ee4be471886018bc7b88f5aee","2.jpg");
TestThreadDemo02 t3 = new TestThreadDemo02("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb.zol-img.com.cn%2Fdesk%2Fbizhi%2Fimage%2F1%2F1680x1050%2F1349289433496.jpg&refer=http%3A%2F%2Fb.zol-img.com.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1618908797&t=fbd6b61bf2cec0bfed9d6ef9e23ce412","3.jpg");
new Thread(t1).start();
new Thread(t2).start();
new Thread(t3).start();
}
}
3. 通过实现Callable接口
package com.zhou3.Thread;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;
/*
使用Callable接口实现多线程
好处:1. 可以定义返回值 2. 可以抛出异常
*/
//多线程类
public class CallableDemo01 implements Callable
2. Lambda表达式
1. Lambda表达式的使用限制
//格式
(paramss) -> expression[表达式]
(paramss) -> statement[语句]
(paramss) -> {statements}
public interface Runnable{
public abstract void run();
}
2. Lambda表达式的简化过程
package com.zhou3.Thread.Lambda;
/*
推导Lambda表达式
*/
public class LambdaDemo01 {
//2.静态内部类
static class Like2 implements iLike{
@Override
public void Lambda() {
System.out.println("I Like Lambda2");
}
}
public static void main(String[] args) {
iLike like = new Like();
like.Lambda();
like = new Like2();
like.Lambda();
//3.局部内部类
class Like3 implements iLike{
@Override
public void Lambda() {
System.out.println("I Like Lambda3");
}
}
like = new Like3();
like.Lambda();
//4.匿名内部类
like = new iLike() {
@Override
public void Lambda() {
System.out.println("I Like Lambda4");
}
};
like.Lambda();
//5.Lambda表达式,是对匿名内部类的再简化
//Lambda表达式就是对程序一步步的简化得来的,由于函数式接口只有一个方法,所以匿名内部类的接口和方法部分就理所当然的被去掉了
like = () -> {
System.out.println("I Like Lambda5");
};
like.Lambda();
}
}
//定义一个函数式接口
interface iLike{
void Lambda();
}
//1.接口实现类
class Like implements iLike{
@Override
public void Lambda() {
System.out.println("I Like Lambda1");
}
}
3. 为什么要使用Lambda表达式呢!
3. 线程的五大状态
1. 线程的操作方法
方法
说明
setPriority(int newPriority)
更改线程的优先级
static void sleep(long millis)
让当前正在执行的线程体休眠指定的毫秒数
void join()
等待该线程终止
static void yield()
暂停正在执行的线程对象,状态退回到就绪状态,重写等待时间片分配
boolean isAlive()
测试线程是否处于活动状态
2. 线程停止
//在主线程中通过公开方法修改标志位来停止线程
package com.zhou3.Thread.ThreadState;
public class StopTest implements Runnable{
//1. 设置全局标志位
private boolean flag = true;
@Override
public void run() {
int i = 0;
while(flag){
System.out.println("Thread time ==" + i++);
}
}
//2. 设置一个线程停止的公开方法
public void threadStop1(){
this.flag = false;
}
public static void main(String[] args) {
StopTest stopTest1 = new StopTest();
new Thread(stopTest1).start();
for (int i = 0; i
3. 线程休眠
package com.zhou3.Thread.ThreadState;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CountDownTest {
public static void main(String[] args) {
Date date1 = new Date(System.currentTimeMillis());//获取当前系统时间
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//格式化时间并输出
System.out.println(new SimpleDateFormat("HH:mm:ss").format(date1));
//刷新当前时间
date1 = new Date(System.currentTimeMillis());
}
}
}
4. 线程礼让
5. 线程强制执行(插队)
package com.zhou3.Thread.ThreadState;
public class TestJoin implements Runnable{
@Override
public void run() {
for (int i = 0; i
6. 线程状态观测
package com.zhou3.Thread.ThreadState;
public class TestStateObservation {
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i
4. 线程优先级
Thread.MIN_PRIORITY = 1;
Thread.MAX_PRIORITY = 10;
Thread.NORM_PRIORITY = 5;
getPriority()
setPriority()
package com.zhou3.Thread.ThreadState;
public class TestPriority {
public static void main(String[] args) {
MyPriority myPriority1 = new MyPriority();
Thread thread1 = new Thread(myPriority1,"1");
Thread thread2 = new Thread(myPriority1,"2");
Thread thread3 = new Thread(myPriority1,"3");
Thread thread4 = new Thread(myPriority1,"4");
Thread thread5 = new Thread(myPriority1,"5");
thread1.start();
thread2.setPriority(1);
thread2.start();
thread3.setPriority(10);
thread3.start();
thread4.setPriority(8);
thread4.start();
thread5.setPriority(3);
thread5.start();
//主线程优先级,默认优先级
System.out.println(Thread.currentThread().getName()+"优先级:"+Thread.currentThread().getPriority());
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"优先级:"+Thread.currentThread().getPriority());
}
}
5. 守护(daemon)线程
6. 线程同步
1. 队列和锁
2. 同步方法
java.util.concurrent //并发包、这是一个有关并发编程的包
7. 死锁
8. Lock锁
9. Lock锁和synchronized关键字的对比
package com.zhou3.Thread.Unsafe;
import java.util.concurrent.locks.ReentrantLock;
/*
lock锁测试
*/
public class TestLock {
public static void main(String[] args){
UnSafe safe1 = new UnSafe();
new Thread(safe1,"hong").start();
new Thread(safe1,"ming").start();
new Thread(safe1,"A").start();
}
}
class UnSafe implements Runnable {
private int ticketNumber = 10;
private final ReentrantLock lock =new ReentrantLock();
@Override
public void run(){
while (true){
try {
lock.lock();
if(ticketNumber
package com.zhou3.Thread.Demo01;
/*
多个线程同时操作同一个对象
*/
public class TestThread {
public static void main(String[] args) {
BuyTicket buyTicket1 = new BuyTicket();
new Thread(buyTicket1,"小美").start();
new Thread(buyTicket1,"黄牛").start();
new Thread(buyTicket1,"懒羊羊").start();
// new Thread(new BuyTicket(),"小美").start();
// new Thread(new BuyTicket(),"大美").start();
// new Thread(new BuyTicket(),"小明").start();
}
}
class BuyTicket implements Runnable{
boolean flag = true;
private int ticketNumber = 10;
@Override
public void run() {
while (flag){
// if(ticketNumber
10. 线程协作
方法名
作用
wait()
线程会一直等待,直到其他线程通知,同sleep不同会释放锁
wait(long timeout)
等待指定毫秒数
notify()
唤醒一个处于等待状态的线程
notifyAll()
唤醒同一个对象上所有调用wait()方法的线程,优先级高的线程优先调度
1. 管程法
package com.zhou3.Thread.ThreadCommunication;
/*
测试生产者消费者模型,管程法
生产者,消费者,产品,缓冲区
*/
public class TestPC {
public static void main(String[] args){
SynContainer container1 = new SynContainer();
Producer producer1 = new Producer(container1);
Consumer consumer1 = new Consumer(container1);
new Thread(producer1,"工具员").start();
new Thread(consumer1,"黑心狗").start();
}
}
class Producer implements Runnable{
SynContainer synContainer1;
//构造器
public Producer(SynContainer synContainer1){
this.synContainer1 = synContainer1;
}
@Override
public void run(){
for (int i = 0; i
2. 信号灯法
package com.zhou3.Thread.ThreadCommunication;
/*
使用信号灯法,实现传小纸条聊天
我,对象,内容
*/
public class TestLight {
public static void main(String[] args) {
Massage massage = new Massage();
new Thread(new My(massage),"my").start();
new Thread(new Zx(massage),"zx").start();
System.out.println("我们会好好的");
}
}
class My implements Runnable{
Massage massage = new Massage();
//我要用这个蓝色的小纸条
public My(Massage massage){
this.massage = massage;
}
//我这次打算写100条“我喜欢你”到小纸条上
@Override
public void run() {
for (int i = 0; i
11. 线程池
线程池的使用
void execute(Runnable command)//执行任务,没有返回值,用来执行Runnable
void shutdown()//关闭线程池
package com.zhou3.Thread.TestPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestPoolRunnable {
public static void main(String[] args) {
//创建线程池
MyThread myThread1 = new MyThread();
ExecutorService service = Executors.newFixedThreadPool(10);
service.execute(myThread1);
service.execute(myThread1);
service.execute(myThread1);
service.execute(myThread1);
service.shutdownNow();
}
}
class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
上一篇:c++ 虚函数