多线程基础

多线程基础,第1张

线程基础 1.任务 多线程 进程

多任务:一个接一个做,不同时

多线程:同时

2.创建方式

1.继承Thread

交替执行,每次执行结果不一样,由cpu调度

package com.liu.www;

//1.继承Thread类 2.重写run方法 3.写main主线程 4.new 对象调用它的start方法
public class TestThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("摸摸大               "+i);
        }

    }

    public static void main(String[] args) {
        //主线程
        TestThread testThread = new TestThread();
        testThread.start();//start相当于开辟了一条新的线程
        for (int i = 0; i < 5000; i++) {
            System.out.println("0000000"+i);
        }
    }
}

图片下载练习:

package com.liu.www;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;

public class TestThread2 extends Thread  {

    private String url;
    private String file;

    public TestThread2(String url, String file) {
        this.url = url;
        this.file = file;
    }

    //下载图片线程的执行体
    @Override
    public void run() {
        ImgDownload imgDownload = new ImgDownload();
        imgDownload.download(url,file);
        System.out.println("下载了文件,文件名是"+file);
    }

    public static void main(String[] args) {
        TestThread2 t1= new TestThread2("https://pics1.baidu.com/feed/03087bf40ad162d9cbb3cc2d87b712eb8a13cd16?token=ba35ec7e6b5f5aeadb4bea873a4e4b27&s=AD717B8444D13DF50839C8140300B091&f=jpeg","1.jpg");
        TestThread2 t2= new TestThread2("https://pics1.baidu.com/feed/1c950a7b02087bf47fe23ffe64bbec2b11dfcf0f?token=39be00f2b209980a21dbaff3c28e1961&s=FEA00DC042E09CE61C38458E0300E002&f=jpeg","2.jpg");
        TestThread2 t3= new TestThread2("https://pics1.baidu.com/feed/279759ee3d6d55fb4833a93bfb4af44d21a4dda3?token=7d10a89c5b4a66f2409156fc61feaf13&s=F21F30C48661974F587271110300C0CA&f=jpeg","3.jpg");

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

    }
}


//下载器类
class ImgDownload{
    public void download(String url,String file ){
        try {
            FileUtils.copyURLToFile(new URL(url),new File(file));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("下载器出现错误");
        }
    }
}
2.实现Runnable

因为java单继承,推荐使用Runnable,多个线程去 *** 作一个对象

package com.liu.www;

//1.继承Thread类 2.重写run方法 3.写main主线程 4.new 线程对象调用它的start方法
public class TestThread3 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("摸摸大               " + i);
        }

    }

    public static void main(String[] args) {
        //主线程
        TestThread3 testThread = new TestThread3();
        //主要就是多这一步,new一个thread,把testThread丢进去
        Thread thread = new Thread(testThread);
        thread.start();
        for (int i = 0; i < 5000; i++) {
            System.out.println("0000000" + i);
        }
    }
}

package com.liu.www;

//并发问题:
//多个线程同时 *** 作一个对象:火车票的例子
public class TestThread4 implements Runnable {
    //票数
    private int ticketNums=10;

    @Override
    public void run() {
        while (true){
            if (ticketNums<=0){
                break;
            }else {
                System.out.println(Thread.currentThread().getName()+ "拿到了第"+ticketNums--+"票");
            }
        }

    }

    public static void main(String[] args) {
        TestThread4 testThread4 = new TestThread4();

        new Thread(testThread4,"周欢").start();
        new Thread(testThread4,"刘可").start();
        new Thread(testThread4,"张钢").start();
    }
}

3.lamda表达式

函数式接口:只包含一个抽象方法

package com.liu.www;


public class Race {

    //3.定义静态内部类(优化1,类在外面很麻烦)
    static class baby2 implements interest{
        @Override
        public void inter() {
            System.out.println("你想要我对lamda感兴趣嘛----two");
        }
    }

    public static void main(String[] args) {
        //定义一个接口的实现类
        interest baby = new baby();
        baby.inter();

        baby = new baby2();
        baby.inter();



        //4.定义局部内部类(优化2,类放在方法里面)
         class baby3 implements interest{
            @Override
            public void inter() {
                System.out.println("你想要我对lamda感兴趣嘛----three");
            }
        }
        baby = new baby3();
        baby.inter();

        //5.匿名内部类(优化3,没有类名,借助父类或者接口)
         baby=new interest() {
             @Override
             public void inter() {
                 System.out.println("你想要我对lamda感兴趣嘛----four");
             }
         };
         baby.inter();

         //6.lamba简化
        baby=()->{
                System.out.println("你想要我对lamda感兴趣嘛----five");
            };
        baby.inter();


    }

}
//1.首先定义函数式接口
interface interest{
    void inter();
}
//2.定义一个类去实现这个接口
class baby implements interest{
    @Override
    public void inter() {
        System.out.println("你想要我对lamda感兴趣嘛");
    }
}

输出结果:
你想要我对lamda感兴趣嘛
你想要我对lamda感兴趣嘛----two
你想要我对lamda感兴趣嘛----three
你想要我对lamda感兴趣嘛----four
你想要我对lamda感兴趣嘛----five
  
这个例子是无参数的,有参数的在()->的()里面写参数即可,参数的类型可以省略
4.线程五大状态

  • 停止线程
    • 建议线程通过设置次数自动停止,不建议死循环

    • 建议使用标志位

    • jdk官方的不推荐的stop(),destroy()不使用

      package com.liu.www;
      

public class Demo_02 implements Runnable{

//1.设置一个标志位
private boolean flag=true;

@Override
public void run() {
    int i=0;
    while (flag){
        System.out.println("------------0000000000"+i++);
    }
}

//2.设置一个公开的方法停止线程,转换标志位
public void stop(){
    this.flag=false;
}

public static void main(String[] args) {
    Demo_02 demo_02 = new Demo_02();
    new Thread(demo_02).start();
    for (int i = 0; i < 10000; i++) {
        System.out.println("主线程正在执行"+i);
        if (i==9000){
            //调用stop方法切换标志位,让线程停止
            demo_02.stop();
            System.out.println("线程停止了");
        }
    }

}

}

  • 线程休眠 sleep() 放大问题的发生性

    package com.liu.www;
    
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class Demo_03 {
    
        public static void main(String[] args) throws InterruptedException {
    //        tendown();
            //打印系统当前时间
            Date date = new Date(System.currentTimeMillis());
    
            while (true){
                Thread.sleep(1000);
                System.out.println(new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss").format(date));
                date = new Date(System.currentTimeMillis());
            }
    
        }
    
        //模拟倒计时
        public static  void tendown() throws InterruptedException {
            for (int i = 10; i >= 0; i--) {
                Thread.sleep(1000);
                System.out.println(i);
            }
        }
    }
    
  • 线程礼让 yield

package com.liu.www;

public class TestYield {
    public static void main(String[] args) {
        myyield my = new myyield();

        new Thread(my,"a").start();
        new Thread(my,"b").start();
    }


}

class myyield implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"线程开始执行");
        Thread.yield();
        System.out.println(Thread.currentThread().getName()+"线程停止执行");
    
}
输出结果:
a线程开始执行
b线程开始执行
a线程停止执行
b线程停止执行 
或者b
a线程开始执行
a线程开始执行
b线程停止执行
b线程停止执行   
  • join() 插队
5.线程优先级

6.守护线程

用户线程:main()

7.线程同步

多个线程 *** 作同一个资源

排队解决:就是队列

锁:景区厕所的门锁

线程同步:就是队列+锁 保证线程的安全性

synchronized:同步的

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xOi6D2Xo-1639320833341)(C:Users密西西比的守望AppDataRoamingTyporatypora-user-imagesimage-20210107230030300.png)]

线程不安全:不安全的主要原因在于线程都有各自的内存,互不影响

  • 出现负数
  • list数据覆盖
第一种方法:synchronized 直接加给方法的
第二种方法:synchronized(obj){ 这个obj是变化的量 增删改
  这里写方法
}

JUC并发编程

死锁:

多个线程互相抱着对方需要的资源,然后形成僵持

lock锁:

jdk5开始出现使用 reentantlock:可重复锁

8.线程协作

生产者消费者问题:

管程法

信号灯法

9.线程池

package com.liu.www;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static java.util.concurrent.Executors.newFixedThreadPool;

//测试线程池
public class TestPool {
    public static void main(String[] args) {
        //1.创建服务,创建线程池 newFixedThreadPool 参数为线程池的大小
        ExecutorService Service = newFixedThreadPool(10);
        Service.execute(new MyThread());
        Service.execute(new MyThread());
        Service.execute(new MyThread());
        Service.execute(new MyThread());

        //2.关闭连接
        Service.shutdown();

    }
}

class MyThread implements Runnable{

    @Override
    public void run() {
            System.out.println(Thread.currentThread().getName());
    }
}
输出结果:
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
pool-1-thread-4  

readPool 参数为线程池的大小
ExecutorService Service = newFixedThreadPool(10);
Service.execute(new MyThread());
Service.execute(new MyThread());
Service.execute(new MyThread());
Service.execute(new MyThread());

    //2.关闭连接
    Service.shutdown();

}

}

class MyThread implements Runnable{

@Override
public void run() {
        System.out.println(Thread.currentThread().getName());
}

}
输出结果:
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
pool-1-thread-4

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5660497.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存