当前位置: 首页 > 科技观察

并发编程说服了我_0

时间:2023-03-16 23:47:01 科技观察

阿芬因为原本的编程习惯,很久没有考虑过并发问题。并发编程的所有内容我都用心学习了,分享给大家。为什么我们需要并发编程?因为我们都知道现在的CPU,内核和线程很多,五花八门,我们并发编程的目的就是为了让程序跑得更快。这里的更快并不是说我们无限的开启更多的线程就可以让程序进行最大可能的并发操作,但是我们在进行并发编程的时候,很容易遇到很多问题,比如死锁问题,还有上下文切换问题,这就是所有的问题。实现多线程的几种方式,面试中最简单的一道题说到这道面试题,很多答案都是大同小异。继承Thread类实现Runnable接口,使用线程池。很多面试官在回答的时候总是回答这三个,但其实实现多线程的方式并不局限于这些方式。比如有返回值的线程实现、定时器实现、内部类实现等。这些方法都可以实现多线程。那么今天就来梳理一下这些不常见的方式吧。其实说实话,匿名内部类的这个方法并不能算是一个新的实现方法,它只是把这个实现方法放到了匿名类中,整体内部实现还是使用InheritThread,实现Runnable接口。案例实现:publicclassTestClass{publicstaticvoidmain(String[]args){//基于子类newThread(){@Overridepublicvoidrun(){while(true){printThreadInfo();}}}.start();//基于接口实现ofnewThread(newRunnable(){@Overridepublicvoidrun(){while(true){printThreadInfo();}}}).start();}privatestaticvoidprintThreadInfo(){System.out.println("当前运行的线程名称是:"+Thread.currentThread().getName());try{Thread.sleep(1000);}catch(Exceptione){thrownewRuntimeException(e);}}}执行结果:当前运行的线程名称为:Thread-1current正在运行的线程名称:Thread-0当前正在运行的线程名称:Thread-1当前正在运行的线程名称:Thread-0当前正在运行的线程名称:Thread-1当前正在运行的线程名称thread:Thread-0正在运行的线程的名称:Thread-0当前正在运行的线程的名称:Thread-1当前正在运行的线程的名称:Thread-1线程的名称ecurrentlyrunningthread:Thread-0当前正在运行的线程名称:Thread-0正在运行的线程名称是:Thread-1其实上面的方法大家肯定都知道,下面说说定时器的实现方法。这种方法其实也是大家经常使用的一种方法,因为我们经常需要在自己不在的时候进行一些操作,比如每天晚上对系统进行统计操作。使用定时器实现publicclassTestClass{privatestaticfinalSimpleDateFormatdateFormat=newSimpleDateFormat("yyyy-MM-ddhh:mm:ss");publicstaticvoidmain(String[]args)throwsException{//创建定时器Timertimer=newTimer();//提交定时任务定时器。schedule(newTimerTask(){@Overridepublicvoidrun(){System.out.println("定时任务执行...");}},dateFormat.parse("2020-12-0820:30:00"));}}你可以复制这段代码,在你设定的时间内执行,不是静态的,需要根据自己的需要去获取。接下来,我们就从并发编程的线程安全说起。接下来阿粉会继续为大家更新关于并发编程的各种技术内容,让大家尽快掌握这个线程安全问题。线程安全其实对于一个对象来说,它是否线程安全完全取决于它是否被多线程访问,而我们想要我们的对象是线程安全的,那么我们必须采用一些方法,而方法有什么?同步机制锁机制也就是大家所熟知的同步加锁的机制。还有使用Volatile类型的变量。也就是说,如果多个线程在访问同一个可变状态变量时没有使用适当的同步,那么程序就会相对错误,解决方法有几种,比如不在线程共享这个变量之前,改变状态变量对于不可变变量,在访问状态变量时使用同步。阿芬之前也看过一张图,意思是他从字节码的角度来分析线程不安全的操作。看下图用最简单的案例给大家讲解一下Synchronized。我们手动实现一个线程,然后自减。每次输出这个变量,最后看到效果图/为了让安全问题更明显,我们让线程执行的时间更长,所以我们休眠10毫秒}catch(InterruptedExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}System.out.println(i);i--;}}}}classTest{publicstaticvoidmain(String[]args){TestClasstestClass=newTestClass();Threadt1=newThread(testClass);Threadt2=newThread(testClass);Threadt3=newThread(testClass);t1.start();t2.start();t3.start();}}不用说了,大家都知道结果一定很乱,有的来回跳转,有的是分段执行,反正不是从100to1.结果大家可以拿代码自己用看看。那么我们加上Synchronized关键字之后呢?publicclassTestClassimplementsRunnable{inti=100;@Overridepublicvoidrun(){while(true){synchronized(this){if(i>0){try{Thread.sleep(10);//为了让安全问题更明显,我们让线程执行时间更长,所以我们休眠10毫秒}catch(InterruptedExceptione){e.printStackTrace();}System.out.println(i);i--;}}}}}classTest{publicstaticvoidmain(String[]args){TestClasstestClass=newTestClass();Threadt1=newThread(testClass);Threadt2=newThread(testClass);Threadt3=newThread(testClass);t1.start();t2.start();t3。start();}}大家可以执行执行结果,顺便把执行结果打印出来。这次是不是很舒服,终于看到了我们一直在想的100-1的内容,但其实我们只是通过添加一个同步关键字来实现线程安全操作,让线程可以同步执行,以及这种不安全的行为将不再发生。是不是很简单?你学会了吗?