Java多线程

原创
10/18 23:11
阅读数 1

多线程

1.程序、进程、线程

  • 在操作系统中运行的程序就是进程;

  • 一个进程可以有多个线程;

  • 程序是指令和数据的有序集合,是一个静态的概念;

  • 而进程则是执行程序的一次执行过程,是一个动态的概念;

  • 进程是系统资源分配的单位

  • 线程是CPU调度和执行的单位

  • 真正的多线程是指多个cpu,即多核

理解:进程相当于一个类,类中有多个方法(即多个线程),main()方法即(主线程),gc线程。

  • main()方法即(主线程)为系统的入口,用于执行整个程序;
  • 线程的运行是由调度器安排调度,不能人为干预;
  • 对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制
  • 线程会带来额外的开销,如cpu的调度时间,并发控制开销
  • 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致

2.线程的创建

  1. 三种创建方式

    • Thread class

      • 继承Thread类
    • Runnable接口

      • 实现Runnable接口
    • Callable接口

      • 实现Callable接口

3.Thread

  • 自定义类继承Thread
  • 重写run()方法;
  • 创建对象,调用start()开启线程
import javax.xml.transform.Source;

public class TestThread01 extends Thread{
    //继承Thread类
//总结:线程开启不一定立即执行,有CPU调度执行

    @Override
    public void run() {
        //run()方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("**********-4564646465");
        }
    }

    //main线程,即主线程
    public static void main(String[] args) {

        TestThread01 testThread01 = new TestThread01();

        //testThread01.start();//线程开启,交替(类似同时)执行,电脑单核只有一个cpu

        testThread01.run();//这个在前,先执行run();

        for (int i = 0; i < 20; i++) {
            System.out.println("7554574545*********");
        }

    }


}

多线程实现多张图片同时下载

import org.apache.commons.io.FileUtils;

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

public class TestThread02 extends Thread{
    private String url;
    private  String name;

   public TestThread02(String url,String name){
       this.url=url;
       this.name=name;
   }
    public TestThread02(){
    }

    @Override
    public void run() {
       //下载线程
        WebDownloader webDownloader = new WebDownloader();
        try {
            webDownloader.downloader(url,name);
            System.out.println(name);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        TestThread02 testThread02 = new TestThread02("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1603037822768&di=5f0cc79b7c104781de8cea48c7d8b1ca&imgtype=0&src=http%3A%2F%2Fattach.bbs.miui.com%2Fforum%2Fmonth_1012%2F10120514509c7244b23f4a2fa5.jpg","a.jpg");
        TestThread02 testThread03 = new TestThread02("https://ns-strategy.cdn.bcebos.com/ns-strategy/upload/fc_big_pic/part-00720-1746.jpg","a1.jpg");
        TestThread02 testThread04 = new TestThread02("https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2441956749,4275399915&fm=26&gp=0.jpg","a2.jpg");
        testThread02.start();
        testThread03.start();
        testThread04.start();
    }

}
//下载器
class WebDownloader{
    //下载方法
    public  void  downloader(String url,String name) throws IOException {

        FileUtils.copyURLToFile(new URL(url),new File(name));

    }
}

4.Runnable

推荐使用Runnable对象,因为Java单继承的局限性

  1. 定义MyRunnable类实现Runnable接口
  2. 实现run()方法,编写线程执行体
  3. 创建线程对象,调用start()方法启动线程
public class TestRunnable01 implements Runnable{

    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("*******************");
        }
    }

    public static void main(String[] args) {
        TestRunnable01 testRunnable01 = new TestRunnable01();
        new Thread(testRunnable01).start();
    }
}

5.小结

  • 继承Thread

    • 子类继承Thread类具备多线程能力
    • 启动线程:子类对象.start()
    • 不建议使用:避免OOP单继承局限性
  • 实现Runnable接口

    • 实现接口Runnable具备多线程能力
    • 启动线程:传入目标对象+Thread对象。start()
    • 推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用

多个线程操作同一个资源问题

//多个线程操作同一个资源
//模拟买票

//发现问题:多个线程操作同一个人资源的情况下,线程不安全,数据紊乱。

public class TestRunnable02 implements Runnable{

    private  int ticket=10;


    public void run() {
        while (true){
            if (ticket<=0){
                break;
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticket--+"票");

        }
    }

    public static void main(String[] args) {
        TestRunnable02 runnable02=new TestRunnable02();
        new Thread(runnable02,"小鹏").start();
        new Thread(runnable02,"小强").start();
        new Thread(runnable02,"小慧").start();
    }
}

6.实例:龟兔赛跑

import org.omg.Messaging.SyncScopeHelper;

public class Race implements Runnable{

    private static String winner;


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

            //模拟兔子睡觉
            if (Thread.currentThread().getName().equals("兔子")&&i%50==0){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            //判断100步
            if (win(i)){
                break;
            }
            System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");
        }
    }

    //判断胜利者
    public boolean win(int step){
        if (winner!=null){
            return true;
        }
        if (step>=100){
            winner=Thread.currentThread().getName();
            System.out.println("胜利者是"+winner);

        }

        return false;
    }

    public static void main(String[] args) {
        Race race=new Race();
        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();
    }
}

7.Callable

展开阅读全文
打赏
0
0 收藏
分享

作者的其它热门文章

加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部