JAVAday23 多线程

本文深入探讨Java多线程的基本概念,包括进程与线程的区别,多线程的开启方式,线程的名称与优先级设置,以及线程的休眠和加入。并通过具体实例演示了如何使用多线程复制文件,创建线程的三种方式,以及解决线程安全问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JAVAday23 多线程

一 多线程基本概念

1.1进程的概念

在了解线程之前先要了解进程,进程就是正在运行的程序,是系统进行资源分配和调度的独立单元。每个进程都有自己的内存空间和系统资源,电脑上可以有多个进程,单核cpu在一个时间点上只有一个进程在运行。但是cpu可以在多个进程间高速切换,感觉像是在同时运行。

1.2线程的概念

线程依赖于进程,进程开启后会有多个任务,每个任务就是线程。线程有随机性,回去抢占cpu的执行权。

并行:逻辑上的同时发生,指应用能够同时执行不同的任务。

并发:物理上的同时发生,指应用能够交替执行不同的任务,在一个时间点上运行多个任务。

JVM是多线程,一个是主线程,另一个是垃圾回收线程。

二 如何开启一个多线程

1.1可以使用JAVA提供的Thread这个类来创建线程。

​ (1)首先定义一个类,继承thread这个类

​ (2)重写thread的run方法

​ (3)创建类的对象

​ (4)开启这个线程

public class MyThread extends Thread{
    @override
    public void run(){
        //run方法就是需要线程来执行的代码,一般耗时的操作,我们就会写在run方法里面,让线程去执行
        forint i= ,i<100,i++{
            System.out.println(i);
        }
        
    }
}
public class MyText{
    public static void main (String [] args){
        MyThread th = new MyThread();
        //开启线程不是调用run方法,调用run方法就是你是用一个对象,调用一个方法,让这个方法执行,线程并没有开启。
        //正确开启线程的方式是调用start(),由线程去调用run方法,执行run方法的代码,同一个线程不要多次开启
        th.start();
    }
}
1.2设置线程名称和优先级
public class MyThread extends Thread{
    @override
    public void run(){
       
        forint i= ,i<100,i++{
            //获取线程的名字
            String name = new this.name
            System.out.println(i);
        }
        
    }
}
public class MyText{
    public static void main (String [] args){
        Thread thread = Thread.currentThread();//获取当前线程对象
        String name = thread.getName();
        MyThread th = new MyThread();
        MyThread th1 = new MyThread();
       //设置线程名称
        th.setName("线程一");
        th1.setName("线程二");
        th.start();
        th1.start()}
}

优先级

public class MyText{
    public static void main (String [] args){
        //java使用线程的调度模型,是抢占式调度
        //如果多个线程的优先级一样,线程的执行就是随机抢占
         MyThread th = new MyThread();
         MyThread th1 = new MyThread();
         //设置线程的优先级
             th.setPriority(Thread.MAX_PRIORITY);
              th1.setPriority(Thread.MIN_PRIORITY);
             //获取线程的优先级
             int priority = th.getPriority();
             int priority1 = th1.getPriority();
             System.out.println(priority);
        	 System.out.println(priority1);
             //默认优先级都是5
             th.start();
        	 th1.start();

        th.start();
    }
}
1.3线程休眠和线程加入
public class MyThread extends Thread{
    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        //让线程休眠 就是让线程处于阻塞状态
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 1000; i++) {
            System.out.println(name);
        }
    }
}
public class MyText {
    public static void main(String[] args) throws InterruptedException {
        //通过构造给线程设置名字
        MyThread th = new MyThread("线程1");
        th.start();
        Thread.sleep(3000);//让当前线程休眠
    }
}
public class MyText {
    public static void main(String[] args) throws InterruptedException {

        MyThread th = new MyThread("线程1");
        MyThread th1 = new MyThread("线程2");
        MyThread th2 = new MyThread("线程3");
        //串行 就是按照顺序去执行
        th.start();
        th.join();
        //join方法在线程开启之后去调用 
        th1.start();
        th1.join();
        th2.start();
        th2.join();

    }
}
public class MyText {
    public static void main(String[] args) throws InterruptedException {
        Thread.currentThread().setName("主线程");
        MyThread th = new MyThread("线程1");
        MyThread th1 = new MyThread("线程2");
        MyThread th2 = new MyThread("线程3");
	//守护线程
      th.setDaemon(true);
      th1.setDaemon(true);
      th2.setDaemon(true);
        System.out.println("主线程挂了");

    }
}
1.4使用线程复制文件
public class CopyThread extends Thread{
    @Override
    public void run() {
        //我复制第一个文件
        try {
            Files.copy(Paths.get("D:\\HBuilderX.1.3.2.20181214.full.zip"), Paths.get("E:\\HBuilderX.1.3.2.20181214.full.zip"), StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class CopyThread2 extends Thread{
    @Override
    public void run() {
        //我复制第二文件
        try {
            Files.copy(Paths.get("MyTest.java"), Paths.get("E:\\hehe.txt"), StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class MyTest {
    public static void main(String[] args) throws IOException {
        //一个线程复制一个 文件
        CopyThread th1 = new CopyThread();
        th1.start();
        //一个线程复制一个 文件
        new CopyThread2().start();
    }
1.5 创建线程的其他两种方式

创建线程的第二种方式

​ (1)创建一个类,实现Runable接口,重写接口中的run方法

​ (2)创建Thread类,对象,将Runable接口的子类对象传递进来

​ (3)调用start()方法开启线程

实现接口的同时可以继承其他类,避免了由于java单继承带来的局限性

public class MyRunable implements Runnable{
    @Override
    public void run() {
        //获取当前线程的名字
        String name = Thread.currentThread().getName();

        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }
}
public class MyText {
    public static void main(String[] args) {
        MyRunnable runable = new MyRunnable();
        Thread th = new Thread(runable);
        th.setName("线程名");
        th.start();

    }

创建线程的第三种方式

public class MyCallable1 implements Callable {
    @Override
    public Object call() throws Exception {
        System.out.println("线程执行了");
        return null;
    }
}
public class MyText {
    public static void main(String[] args) {
        MyCallable1 callable1 = new MyCallable1();
        FutureTask<Integer> task = new FutureTask<Integer>(callable1);
        Thread thread = new Thread(task);
        thread.start();
    }
}

三 买票实例以及同步代码块解决线程安全问题

3.1Thread类实现
public class CellThread extends Thread{
    static int piao = 100;//设置为静态变量就可以共享这100张票,否则每个成员都可以获得100张
    @Override
    public void run() {
        while (true){
            if(piao>1){
                String name = this.getName();

                System.out.println(name+"正在出售"+piao--);
            }
        }
    }
}
public class MyText {
    public static void main(String[] args) {
        CellThread th1 = new CellThread();
        CellThread th2 = new CellThread();
        CellThread th3 = new CellThread();
        th1.setName("窗口1");
        th2.setName("窗口2");
        th3.setName("窗口3");

        th1.start();
        th2.start();
        th3.start();



    }
}
3.2用runable接口实现
public class CellRunable implements Runnable {
    int piao = 100;

    @Override
    public void run() {

        while (true) {
            if (piao > 1) {

                System.out.println("正在出售" + piao--);
            }

        }

    }
public class MyText {
    public static void main(String[] args) {
        CellRunable runable1 = new CellRunable();
        CellRunable runable2 = new CellRunable();
        CellRunable runable3 = new CellRunable();
        Thread th1 = new Thread(runable1);
        Thread th2 = new Thread(runable1);
        Thread th3 = new Thread(runable1);
        //三个线程同时执行一个任务,所以不用加静态

        th1.setName("窗口1");
        th2.setName("窗口2");
        th3.setName("窗口3");

        th1.start();
        th2.start();
        th3.start();



    }
}
3.3线程安全问题

在模拟了网络延时的情况后,出现了

相同票 是由于原子性所导致的 piao–不是一个原子性的操作 原子性:不可在分割

0票或负票 由线程的唯一性所导致

出现数据安全问题,要满足按个条件

​ (1)要是多线程环境

​ (2)多线程在并发操作共享数据

​ (3)有多条语句在操作这个共享数据

可以使用同步代码块来解决线程安全问题

将有线程安全问题的代码包裹在synchronized

public class CellRunable implements Runnable {
    int piao = 100;
    static Object obj = new Object();//多个对象要用一把锁
    @Override
    public void run() {
        while (true) {
            //在实际购票时会有网络延迟,可以使用休眠来模拟网络延迟
            synchronized (obj) {//锁,就是一个任意对象
                if (piao > 1) {
                    try {
                        Thread.sleep(200);//模拟网络延迟
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"正在出售" + piao--);
                }
            }
            //释放锁
        }

    }
}
public class MyText {
    public static void main(String[] args) {
        CellRunable runable1 = new CellRunable();
        CellRunable runable2 = new CellRunable();
        CellRunable runable3 = new CellRunable();
        Thread th1 = new Thread(runable1);
        Thread th2 = new Thread(runable1);
        Thread th3 = new Thread(runable1);
        //三个线程同时执行一个任务,所以不用加静态

        th1.setName("窗口1");
        th2.setName("窗口2");
        th3.setName("窗口3");

        th1.start();
        th2.start();
        th3.start();



    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值