打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
线程和简单并发问题

线程的一些概念

​ 很多多线程是模拟出来的,真整的多线程是指有多个cpu,即多核,如服务器。如果是模拟出来的多线程,在一个cpu的情况下,同一个时间点,cpu只能执行一个代码,因为切换的快,所以就有同时执行的错觉。

​ @线程是独立的执行路径

​ @在程序运行时,即使自己没有创建线程,后台也会有多个线程,如主线程,gc线程

​ @在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序不能人为干预

​ @线程会带来额外的开销,如cpu调度时间,并发控制开销

​ @对同一份资源操作时,会存在资源抢夺问题,需要加入并发控制

​ @每个线程在自己的工作内存交互,内存控制不当会造成数据不一致

Java中线程的创建

1 . 继承Thread类
//创建线程方式一:继承Thread类,重写run()方法,调用start()开启线程
public class TestThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 20; i++){
            System.out.println("我是线程,我在执行第"+i+"次");
        }
    }
    public static void main(String[] args) {
        TestThread testThread = new TestThread();
        testThread.start();

        for (int i = 0; i < 400; i++){
            System.out.println("hhhhhhhhh,我在执行第"+i+"次");
        }
    }
}

这是上述代码的执行结果,可以看出线程与主线程是交替运行的。

​ 线程开启不一定立即执行,而是等待CPU调度执行

2.实现Runnable接口

//创建线程方式2: 实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start()方法
public class ThreadTest_02 implements Runnable{
    @Override
    public void run() {
        for(int i  = 0 ;i<20;i++){
            System.out.println("AaAAAAAAA"+"   "+i);
        }
    }

    public static void main(String[] args) {
        ThreadTest_02 thread01 = new ThreadTest_02();
        //Thread thread = new Thread(thread01);
        //thread.start();
        /*
        	上面注释里是另一种调用方法,推荐使用下面的方法
        */
        new Thread(thread01).start();


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

推荐使用实现Runnable接口的方式,可以避免单继承局限性,灵活方便,方便同一个对象被多个对象使用

3.实现Callable接口

线程在操作系统中的调度

1.新生状态

Thread t = new Thread();

​ 当线程对象一旦创建,就进入新生状态。

2.就绪

​ 当线程对象调用start()方法,线程立即进入就绪状态,就绪状态是指可以被CPU调度,而不是立即被调度。

3.运行

​ 当就绪状态的线程被CPU调度后,线程就进入运行状态。此时线程才会真正执行线程体的代码块。

4.阻塞

​ 在操作系统中,当一个线程需要等待前提条件的完成时,比如IO;又或者将CPU分配的时间片用完后就会进入阻塞状态,等待CPU再次分配资源。在Java中,当调用sleep(),wait()方法或者同步锁定时,线程就会进入阻塞状态,代码停止继续往下执行,阻塞事件解出后,重新进入就绪状态等待CPU再次分配资源。

5.Dead

​ 当线程中断或者结束,就进入死亡状态,不能再次被启动。

关于Thread类的一些方法

方法 说明
setPriority(int newPriority) 更改线程优先级
static void sleep(long millis) 在指定的毫秒数内让正在执行的线程休眠
void join() 等待该线程终止
static void yield() 暂停当前正在执行的线程对象,并执行其他线程
void interrupt() 中断线程,不推荐使用此方式
boolean isAlive() 测试线程是否处于活动状态

停止线程

@不推荐使用JDK提供的stop()、destroy()方法【已经弃用】

@推荐线程自己停止下来

@建议使用一个标志位进行终止变量当flag = flase,则终止线程运行

//测试停止线程
public class Test_01 implements Runnable {
    //设置一个标识位

    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while (flag) {
            System.out.println("第" + i++ + "次");
            //if (i>9999){
            //    stop();
            //    System.out.println("线程停止");
            //}
        }
    }

    //自己定义一个stop方法,用于转换标志位从而使线程停止
    public void stop() {
        this.flag = false;
    }

    public static void main(String[] args) {
        Test_01 test = new Test_01();
        new Thread(test).start();
        
		//主线程,当主线程输出999次时,将标志位转换为flase
        for (int i = 0; i < 1000; i++) {
            System.out.println("main:" + i);
            if (i == 999) {
                test.stop();
                System.out.println("线程停止");
            }
        }
    }
}

并发问题

多个线程操作同一个资源的情况下,数据不安全

//多个线程操作一个对象实例
//买火车票
public class ThreadTest_03 implements Runnable{
    private int ticketNums = 15;
	@Override
    public void run() {
        while(true){
            if(ticketNums <= 0){
                break;
            }

            System.out.println("恭喜"+Thread.currentThread().getName()+"拿到了第"+ticketNums--+"张票");
        }
    }

    public static void main(String[] args) {
        ThreadTest_03 t1 =new ThreadTest_03();


       new Thread(t1,"wsl").start();
        new Thread(t1,"gxx").start();
        new Thread(t1,"黄牛").start();
    }
}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
08语法总结 - 线程
对java中的线程感想
Java 多线程的三种实现方法
计算机是如何工作的,Java多线程编程
个人珍藏的80道多线程并发面试题(11-20答案解析)
Java并发入门原理教程(一)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服