-
java线程中start和run方法的区别
Start:
用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的 start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到spu时间片,就开始执行run()方法,这里方法 run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。Run:
run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。
查看全部 -
1.原子性:
Java内存模型只保证了基本读取和赋值是原子性操作,如果要实现更大范围操作的原子性,可以通过synchronized和Lock来实现。由于synchronized和Lock能够保证任一时刻只有一个线程执行该代码块,那么自然就不存在原子性问题了,从而保证了原子性。
2.可见性:
对于可见性,Java提供了volatile关键字来保证可见性。当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。而普通的共享变量不能保证可见性,因为普通共享变量被修改之后,什么时候被写入主存是不确定的,当其他线程去读取时,此时内存中可能还是原来的旧值,因此无法保证可见性。
另外,通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。
3.有序性
在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。
在Java里面,可以通过volatile关键字来保证一定的“有序性”(具体原理在下一节讲述)。另外可以通过synchronized和Lock来保证有序性,很显然,synchronized和Lock保证每个时刻是有一个线程执行同步代码,相当于是让线程顺序执行同步代码,自然就保证了有序性。
另外,Java内存模型具备一些先天的“有序性”,即不需要通过任何手段就能够得到保证的有序性,这个通常也称为 happens-before 原则。如果两个操作的执行次序无法从happens-before原则推导出来,那么它们就不能保证它们的有序性,虚拟机可以随意地对它们进行重排序。
http://www.cnblogs.com/dolphin0520/p/3920373.html查看全部 -
建议:
1、Java Memory Mode:JMM描述了java线程如何通过内存进行交互,了解happens-before,synchronized,voliatile & final
2、Locks % Condition:锁机制和等待条件的高层实现 java.util,concurrent.locks
3、线程安全性:原子性与可见性,死锁等
4、多线程常用的交互模型
· Producer-Consumer模型
· Read-Write Lock模型
· Future模型
· Worker Thread模型
5、Java5中并发编程工具:java.util.concurrent 线程池ExcutorService Callable&Future BlockingQueue
6、推荐书本:CoreJava & JavaConcurrency In Practice查看全部 -
互斥:关键数据在一个时间被一个线程使用。
同步实现:object 方法wait()/notify()/notifyAll();
wait set 类似于线程的休息室,访问共享数据的代码称为critical section。一个线程获取锁,然后进入临界区 ,发现某些条件不满足,然后调用锁对象上的wait方法,然后线程释放锁资源,进入锁对象上的wait set。其他线程可以获取所资源,然后执行,完了以后调用notify()/notifyAll(),唤醒锁对象上的一个/全部等待线程,有机会在当前线程离开临界资源释放锁之后竞争临界资源的锁对象。查看全部 -
互斥与同步的代码实现
查看全部 -
@Java线程——线程交互——互斥与同步
一、互斥
同一时间,只能有一个线程访问数据
二、同步
一种通信机制,一个线程操作完成后,以某种方式通知其他线程
三、实现方法
1、【互斥】构建锁对象(Object objLock),通过synchronized(lockObj){ 互斥的代码块 }
2、加锁操作会开销系统资源,降低效率
3、在某线程的条件不满足任务时,使用lockObj.wait()对线程进行阻挡,防止其继续竞争CPU资源,滞留在wait set中,等待唤醒,【唤醒后继续完成业务】
4、【同步】在某一代码正确执行完业务后,通过lockObj.notifyAll()唤醒所有在lockObj对象等待的线程查看全部 -
@Java线程——线程交互——争用条件
1、当多个线程同时共享访问同一数据(内存区域)时,每个线程都尝试操作该数据,从而导致数据被破坏(corrupted),这种现象称为争用条件
2、原因是,每个线程在操作数据时,会先将数据初值读【取到自己获得的内存中】,然后在内存中进行运算后,重新赋值到数据。
3、争用条件:线程1在还【未重新将值赋回去时】,线程1阻塞,线程2开始访问该数据,然后进行了修改,之后被阻塞的线程1再获得资源,而将之前计算的值覆盖掉线程2所修改的值,就出现了数据丢失情况查看全部 -
线程常用方法
1.获取线程名称:getName();
2.取得当前线程对象:currentThread();
3.判断是否启动:isAlive();
4.强行运行:join();
5.线程休眠:sleep();
6.线程礼让:yield();线程停止:
1、调用stop()方法会使线程戛然停止,而无法知道线程任务完成情况,官方已经不推荐使用。
2、interrupt()方法设置线程的标识位,并在线程中判断标志位的状态,从而结束线程,但是当在线程中开启了另外的线程时,比如在线程中Tread.sleep(),这时候调用interrupt()方法设置标志位可能设置的是你想要停止的线程,也可能是想要停止的线程中的线程的标志位,因此interrupt()方法也并不能很好的结束线程。
3、第三种方法,在线程的类声明一个volatile变量来记录线程的状态,相当于interrupt()方法那样,volatile关键字表示线程中的变量可以接受外部其他线程改变。因此可以在需要停止的地方设置volatile声明的变量的值设置为状态,并在执行run()函数里判断是否结束。
什么时候使用thread 什么时候使用runnable
其实两种方式效果一样,但推荐使用runnable
因为Java是单继承,继承了thread就不能继承其他的类
而实现runnable接口的话,扩展性要好很多查看全部 -
interrupt()方法不会中断一个正在运行的线程。
>实际上,在线程受到阻塞时抛出一个中断信号,调用interrupt()方法会使该线程退出阻塞状态。
>更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态,然后该线程还是继续运行的。@Java线程——如何正确停止线程
一、错误一:stop()方法
1、not stop:stop()方法会使线程戛然而止
2、使程序突然中止,无法完成完整的业务步骤,也无法进行清理工作二、错误二:interrupt()方法
interrupt()方法只能设置interrupt标志位(且在线程阻塞情况下,标志位会被清除,更无法设置中断标志位),无法停止线程三、正确方法:设置退出标志
1、使用退出标志位来停止while循环
2、完成最后一次业务后跳出while循环后,之后进行一些清理工作查看全部 -
如何正确停止线程?
--使用退出标志
如本文:volatile boolean keepRunning=true;
这样做的好处是:使得线程有机会使得一个完整的业务步骤被完整地执行,在执行完业务步骤后有充分的时间去做代码的清理工作,使得线程代码在实际中更安全查看全部 -
stop方法使得线程戛然而止,完成了什么工作,哪些工作还没有做,都不知道,且清理工作也没有做,所以不是正确的停止线程方法
正确的停止线程方法是,在线程执行中设置状态标识,通过控制标识来控制线程正常完整的执行结束线程
volatile是保证所有子线程里的变量都能同步到主内存里变量的值
不要用stop()方法结束线程查看全部 -
Stage舞台继承了Thread类,其实它相当于一个总线程,用于控制多个线程协同工作的,yield()方法是让当前线程可以让出处理器,让多条线程可以同时进行的关键,join()方法就相当于等待线程,由于各个线程独立运行互不干扰,当它们同时进行的时候,会出现某个线程过早结束的情况,本例中的Stage总线程如果不在"程咬金"线程出现的时候使用join方法,它就会在启动了"程咬金"线程之后运行结束,导致舞台剧过早结束,所以用join方法来等待"程咬金"线程,只有当使用了join方法的线程运行完毕了之后,也就是等待"程咬金"线程运行完毕以后,才是舞台剧的谢幕
查看全部 -
通过线程的方法来控制线程
start()开始线程。
sleep()方法可以使线程休眠。
yield()让出当前线程的执行权限,随机选择线程执行。
join()优先执行该线程,其他线程都暂停。查看全部 -
1.加入join是为了让舞台线程最后停止,如果不加有可能舞台线程结束,军队线程还未停止,就好比导演喊停,演员还在演!可以在join后面加入测试语句System.out.println("舞台结束!");,然后去掉或者保留join观察效果。
2.volatile 关键字 保证了线程可以正确地读取其他线程写入的值,如果不写成volatile,由于可见性的问题,当前线程有可能不能读到这个值//可见性JMM(JAVA内存模型)happens-before原则、可见性原则
用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的值
3.Thread.yield();//让出处理器时间,公平竞争查看全部 -
1.在同一时间,同一处理器或同一个核只能运行一条线程,当一条线程休眠之后,另一条线程才获得了我们处理器的时间
2.一个.java文件中可以有多个类,但是只能有一个public修饰的类
3.Runnable接口之中没有getName方法,我们可以使用Thread的静态方法currentThreat().getName()获取该对象的名字。
4.若实现接口通过Thread.currentThread().getName()方法获取当前线程名称,继承Thread则getName()方法获取当前线程。查看全部
举报