修改wordpress上传路径,莱芜seo,腾讯网站建设方案,网站seo思路世界那么大#xff0c;谢谢你来看我#xff01;#xff01;关注我你就是个网络、电脑、手机小达人什么是进程#xff1f;电脑中时会有很多单独运行的程序#xff0c;每个程序有一个独立的进程#xff0c;而进程之间是相互独立存在的。比如下图中的QQ、酷狗播放器、电脑管… 世界那么大谢谢你来看我关注我你就是个网络、电脑、手机小达人什么是进程电脑中时会有很多单独运行的程序每个程序有一个独立的进程而进程之间是相互独立存在的。比如下图中的QQ、酷狗播放器、电脑管家等等。什么是线程进程想要执行任务就需要依赖线程。换句话说就是进程中的最小执行单位就是线程并且一个进程中至少有一个线程。那什么是多线程提到多线程这里要说两个概念就是串行和并行搞清楚这个我们才能更好地理解多线程。所谓串行其实是相对于单条线程来执行多个任务来说的我们就拿下载文件来举个例子当我们下载多个文件时在串行中它是按照一定的顺序去进行下载的也就是说必须等下载完A之后才能开始下载B它们在时间上是不可能发生重叠的。并行下载多个文件开启多条线程多个文件同时进行下载这里是严格意义上的在同一时刻发生的并行在时间上是重叠的。了解了这两个概念之后我们再来说说什么是多线程。举个例子我们打开腾讯管家腾讯管家本身就是一个程序也就是说它就是一个进程它里面有很多的功能我们可以看下图能查杀病毒、清理垃圾、电脑加速等众多功能。按照单线程来说无论你想要清理垃圾、还是要病毒查杀那么你必须先做完其中的一件事才能做下一件事这里面是有一个执行顺序的。如果是多线程的话我们其实在清理垃圾的时候还可以进行查杀病毒、电脑加速等等其他的操作这个是严格意义上的同一时刻发生的没有执行上的先后顺序。以上就是一个进程运行时产生了多个线程。在了解完这个问题后我们又需要去了解一个使用多线程不得不考虑的问题——线程安全。今天我们不说如何保证一个线程的安全我们聊聊什么是线程安全因为我之前面试被问到了说真的我之前真的不是特别了解这个问题我们好像只学了如何确保一个线程安全却不知道所谓的安全到底是什么什么是线程安全当多个线程访问某个方法时不管你通过怎样的调用方式、或者说这些线程如何交替地执行我们在主程序中不需要去做任何的同步这个类的结果行为都是我们设想的正确行为那么我们就可以说这个类是线程安全的。既然是线程安全问题那么毫无疑问所有的隐患都是在多个线程访问的情况下产生的也就是我们要确保在多条线程访问的时候我们的程序还能按照我们预期的行为去执行我们看一下下面的代码。Integer count 0;public void getCount() { count ; System.out.println(count); }很简单的一段代码下面我们就来统计一下这个方法的访问次数多个线程同时访问会不会出现什么问题我开启的3条线程每个线程循环10次得到以下结果我们可以看到这里出现了两个26出现这种情况显然表明这个方法根本就不是线程安全的出现这种问题的原因有很多。最常见的一种就是我们A线程在进入方法后拿到了count的值刚把这个值读取出来还没有改变count的值的时候结果线程B也进来的那么导致线程A和线程B拿到的count值是一样的。那么由此我们可以了解到这确实不是一个线程安全的类因为他们都需要操作这个共享的变量。其实要对线程安全问题给出一个明确的定义还是蛮复杂的我们根据我们这个程序来总结下什么是线程安全。当多个线程访问某个方法时不管你通过怎样的调用方式、或者说这些线程如何交替地执行我们在主程序中不需要去做任何的同步这个类的结果行为都是我们设想的正确行为那么我们就可以说这个类是线程安全的。搞清楚了什么是线程安全接下来我们看看JAVA中确保线程安全最常用的两种方式。先来看段代码。public void threadMethod(int j) { int i 1; j j i;}1234567大家觉得这段代码是线程安全的吗毫无疑问它绝对是线程安全的我们来分析一下为什么它是线程安全的我们可以看到这段代码是没有任何状态的就是说我们这段代码不包含任何的作用域也没有去引用其他类中的域进行引用它所执行的作用范围与执行结果只存在它这条线程的局部变量中并且只能由正在执行的线程进行访问。当前线程的访问不会对另一个访问同一个方法的线程造成任何的影响。两个线程同时访问这个方法因为没有共享的数据所以他们之间的行为并不会影响其他线程的操作和结果所以说无状态的对象也是线程安全的。添加一个状态呢如果我们给这段代码添加一个状态添加一个count来记录这个方法并命中的次数每请求一次count1那么这个时候这个线程还是安全的吗public class ThreadDemo { int count 0; // 记录方法的命中次数 public void threadMethod(int j) { count ; int i 1; j j i; }}1234567891011121314明显已经不是了单线程运行起来确实是没有任何问题的但是当出现多条线程并发访问这个方法的时候问题就出现了我们先来分析下count1这个操作。进入这个方法之后首先要读取count的值然后修改count的值最后才把这把值赋值给count总共包含了三步过程“读取”一“修改”一“赋值”既然这个过程是分步的那么我们先来看下面这张图看看你能不能看出问题可以发现count的值并不是正确的结果当线程A读取到count的值但是还没有进行修改的时候线程B已经进来了然后线程B读取到的还是count为1的值正因为如此所以我们的count值已经出现了偏差那么这样的程序放在我们的代码中是存在很多的隐患的。如何确保线程安全既然存在线程安全的问题那么肯定得想办法解决这个问题怎么解决我们说说常见的几种方式synchronizedsynchronized关键字就是用来控制线程同步的保证我们的线程在多线程环境下不被多个线程同时执行确保我们数据的完整性使用方法一般是加在方法上。public class ThreadDemo { int count 0; // 记录方法的命中次数 public synchronized void threadMethod(int j) { count ; int i 1; j j i; }}1234567891011121314这样就可以确保我们的线程同步了同时这里需要注意一个大家平时忽略的问题首先synchronized锁的是括号里的对象而不是代码其次对于非静态的synchronized方法锁的是对象本身也就是this。当synchronized锁住一个对象之后别的线程如果想要获取锁对象那么就必须等这个线程执行完释放锁对象之后才可以否则一直处于等待状态。注意点虽然加synchronized关键字可以让我们的线程变得安全但是我们在用的时候也要注意缩小synchronized的使用范围如果随意使用时很影响程序的性能别的对象想拿到锁结果你没用锁还一直把锁占用这样就有点浪费资源。lock先来说说它跟synchronized有什么区别吧Lock是在Java1.6被引入进来的Lock的引入让锁有了可操作性什么意思就是我们在需要的时候去手动的获取锁和释放锁甚至我们还可以中断获取以及超时获取的同步特性但是从使用上说Lock明显没有synchronized使用起来方便快捷。我们先来看下一般是如何使用的private Lock lock new ReentrantLock(); // ReentrantLock是Lock的子类 private void method(Thread thread){ lock.lock(); // 获取锁对象 try { System.out.println(线程名thread.getName() 获得了锁); // Thread.sleep(2000); }catch(Exception e){ e.printStackTrace(); } finally { System.out.println(线程名thread.getName() 释放了锁); lock.unlock(); // 释放锁对象 } }123456789101112131415进入方法我们首先要获取到锁然后去执行我们业务代码这里跟synchronized不同的是Lock获取的所对象需要我们亲自去进行释放为了防止我们代码出现异常所以我们的释放锁操作放在finally中因为finally中的代码无论如何都是会执行的。写个主方法开启两个线程测试一下我们的程序是否正常public static void main(String[] args) { LockTest lockTest new LockTest(); // 线程1 Thread t1 new Thread(new Runnable() { Override public void run() { // Thread.currentThread() 返回当前线程的引用 lockTest.method(Thread.currentThread()); } }, t1); // 线程2 Thread t2 new Thread(new Runnable() { Override public void run() { lockTest.method(Thread.currentThread()); } }, t2); t1.start(); t2.start(); }1234567891011121314151617181920212223242526结果可以看出我们的执行是没有任何问题的。其实在Lock还有几种获取锁的方式我们这里再说一种就是tryLock()这个方法跟Lock()是有区别的Lock在获取锁的时候如果拿不到锁就一直处于等待状态直到拿到锁但是tryLock()却不是这样的tryLock是有一个Boolean的返回值的如果没有拿到锁直接返回false停止等待它不会像Lock()那样去一直等待获取锁。我们来看下代码private void method(Thread thread){ // lock.lock(); // 获取锁对象 if (lock.tryLock()) { try { System.out.println(线程名thread.getName() 获得了锁); // Thread.sleep(2000); }catch(Exception e){ e.printStackTrace(); } finally { System.out.println(线程名thread.getName() 释放了锁); lock.unlock(); // 释放锁对象 } } }123456789101112131415结果我们继续使用刚才的两个线程进行测试可以发现在线程t1获取到锁之后线程t2立马进来然后发现锁已经被占用那么这个时候它也不在继续等待。似乎这种方法感觉不是很完美如果我第一个线程拿到锁的时间比第二个线程进来的时间还要长是不是也拿不到锁对象那我能不能用一中方式来控制一下让后面等待的线程可以等待5秒如果5秒之后还获取不到锁那么就停止等其实tryLock()是可以进行设置等待的相应时间的。private void method(Thread thread) throws InterruptedException { // lock.lock(); // 获取锁对象 // 如果2秒内获取不到锁对象那就不再等待 if (lock.tryLock(2,TimeUnit.SECONDS)) { try { System.out.println(线程名thread.getName() 获得了锁); // 这里睡眠3秒 Thread.sleep(3000); }catch(Exception e){ e.printStackTrace(); } finally { System.out.println(线程名thread.getName() 释放了锁); lock.unlock(); // 释放锁对象 } } }12345678910111213141516171819结果看上面的代码我们可以发现虽然我们获取锁对象的时候可以等待2秒但是我们线程t1在获取锁对象之后执行任务缺花费了3秒那么这个时候线程t2是不在等待的。我们再来改一下这个等待时间改为5秒再来看下结果private void method(Thread thread) throws InterruptedException { // lock.lock(); // 获取锁对象 // 如果5秒内获取不到锁对象那就不再等待 if (lock.tryLock(5,TimeUnit.SECONDS)) { try { System.out.println(线程名thread.getName() 获得了锁); }catch(Exception e){ e.printStackTrace(); } finally { System.out.println(线程名thread.getName() 释放了锁); lock.unlock(); // 释放锁对象 } } }12345678910111213141516结果这个时候我们可以看到线程t2等到5秒获取到了锁对象执行了任务代码。以上就是使用Lock来保证我们线程安全的方式。声明本人分享该教程是希望大家通过这个教程了解信息安全并提高警惕本教程仅限于教学使用不得用于其他用途触犯法律本人一概不负责请知悉免责声明本文旨在传递更多市场信息不构成任何投资建议和其他非法用途。文章仅代表作者观点不代表手机电脑双黑客立场。以上文章之对于正确的用途仅适用于学习