JAVA 多线程

1、多线程概念

与操作系统中多线程差不多,但是JAVA中的多线程是对虚拟机,
而操作系统是面向实实在在的硬件(更复杂)。利用资源处理任务的思路相同。

2、此处线程

  • 每个线程拥有独立的运行栈和程序计数器(PC),线程切换的开销小
  • 一个进程中的多个线程共享相同的内存单元/内存地址空间。它们从同一堆中分配对象,可以访问相同的变量和对象。使得线程的通信简便、高效。但多个线程操作系统共享的资源有安全隐患。(深入理解需要长期不断学习,迭代更新)

3、线程的简单创建

1、方式一

1.创建一个继承于Thread的子类
2.重写Thread的run()>>>此线程需要做的事写在此处
3.创建Thread的对象
4.通过此对象调用start()( 作用:启动线程,去调用run())
注意:

  • 不能用 对象.run() 启动线程
  • 一个对象只能用一次start()

创建一个线程:

线程一

package com.learn.thread;
/**继承Thresd
 */
//1.创建一个继承于Thread的子类
public class LearnThread_01 extends Thread {

    //2.重写Thread的run()
    @Override
    public void run() {
        //找出1-100的偶数
        for (int i = 1; i <= 100; i++) {
            if (i%2 == 0) {
                System.out.println("线程一:"+i);
            }
        }
    }
}

线程二

package com.learn.thread;

public class LearnThread_02 extends Thread{
    @Override
    //找出1-100 奇数
    public void run() {
        for (int i = 1; i <= 100; i++) {
            if (i%2 != 0) {
                System.out.println("线程二:"+i);
            }
        }
    }
}

测试

package com.learn.thread;

public class AllThread {
    public static void main(String[] args) {
        LearnThread_01 learnThread1 = new LearnThread_01();
        learnThread1.start();
        //主线程
        for (int i = 1; i <= 100; i++) {
            if (i%2 != 0) {
                System.out.println("线程二:"+i);
            }
        }
    }
}

结果:这里已经乱了哦(体现了线程的思想,此处线程不安全)
在这里插入图片描述补充1:Thread中常用方法

  • satar()========================启动线程、调用run()
  • run()=========================子类重写建立需要的操作
  • currentThread()=================静态方法,返回执行当前代码的线程
  • getName()=====================获取当前线程的名字
  • setName()=====================设置当前线程的名字
  • yield()========================释放当前Cpu的使用
  • sleep()=======================停等(1000)单位为毫秒
  • join()========================在线程A调用线程B时,A阻塞直到B完成结束阻塞

补充2:线程的优先级

0000&*&

  • NAX_PRIORITY :10
  • NAX_PRIORITY :5 (默认优先级)
  • NAX_PRIORITY :1
    &*&
    setPriority();
    getPriority()

2、方式二

  1. 创建一个实现Runnable 接口的类
  2. 实现抽象方法run()
  3. 创建实现类的对象
  4. 将此对象作为参数传递Thread类的构造器中,创建Thread的对象
  5. 通过Thread的对象调用start()
package com.learn.thread;

public class RunLearThread implements Runnable{
    @Override
    public void run() {
        //找出1-100的偶数
        for (int i = 1; i <= 100; i++) {
            if (i%2 == 0) {
                System.out.println("Runnable 实现");
            }
        }
    }
}

测试

@Test
    public void test_02(){
        RunLearThread run = new RunLearThread();
        Thread thread = new Thread(run);
        thread.start();
    }

结果:
在这里插入图片描述

4、线程安全

1、线程的生命周期(java)
在这里插入图片描述

2、解决简单线程安全问题
方式一:同步代码块

  1. synchronized(同步监视器){
    //需要同步的代码块
    }

  2. 对共享数据的操作需要同步

  3. 同步监视器就是锁,java中对象充当锁。多个线程只能用一把锁。

代码一

package com.security.thread;

public class Win implements Runnable{

    private  int ticket = 100;
    int counter = 0;
    Object obje = new Object();

    @Override
    public void run() {
        //同步代码块实现线程安全
        synchronized(obje){

        while (true){
            if (ticket >0) {
                //睡
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                counter++;
                System.out.println(Thread.currentThread().getName()+"卖票,票号为:"+ticket+"\n"+"卖出的票数:"+counter);
                ticket--;
            }else {
                break;
            }
        }
    }
    }
}

代码测试

package com.security.thread;


public class SealTikets {
    public static void main(String[] args) {
        Win win1= new Win();
        Thread thread1 = new Thread(win1);
        Thread thread2 = new Thread(win1);
        Thread thread3 = new Thread(win1);

        thread1.setName("窗口1");
        thread2.setName("窗口2");
        thread3.setName("窗口3");

        thread1.start();
        thread2.start();
        thread3.start();
    }
}

测试结果

窗口1卖票,票号为:100
卖出的票数:1
窗口1卖票,票号为:99
卖出的票数:2
窗口1卖票,票号为:98
卖出的票数:3
窗口1卖票,票号为:97
卖出的票数:4
窗口1卖票,票号为:96
卖出的票数:5
窗口1卖票,票号为:95
卖出的票数:6
窗口1卖票,票号为:94
卖出的票数:7
窗口1卖票,票号为:93
卖出的票数:8
窗口1卖票,票号为:92
卖出的票数:9
.............................................................

线程已经全!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

方式二:同步方法

run 方法用 synchronized 修饰即可

package com.sec.method;

public class Wind implements Runnable{

    private  int ticket = 100;
    int counter = 0;
    //同步方法
    @Override
    public synchronized void  run() {
        while (true){
            if (ticket >0) {
                //睡100 毫秒
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                counter++;
                System.out.println(Thread.currentThread().getName()+"卖票,票号为:"+ticket+"\n"+"卖出的票数:"+counter);
                ticket--;
            }else {
                break;
            }
        }
    }
}


运行结果:

窗口1卖票,票号为:100
卖出的票数:1
窗口1卖票,票号为:99
卖出的票数:2
窗口1卖票,票号为:98
卖出的票数:3
窗口1卖票,票号为:97
卖出的票数:4
窗口1卖票,票号为:96
卖出的票数:5
窗口1卖票,票号为:95
卖出的票数:6
窗口1卖票,票号为:94
卖出的票数:7
窗口1卖票,票号为:93
卖出的票数:8
窗口1卖票,票号为:92
卖出的票数:9
.............................................................

小结:目前实现线程安全有四种方法
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值