J2EE-线程
来源:互联网 发布:网络yy语音授课是什么 编辑:程序博客网 时间:2024/05/17 23:32
1、什么是线程
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
2、线程状态(图)
- 调用join()和sleep()方法,sleep()时间结束或被打断,join()中断,IO完成都会回到Runnable状态,等待JVM的调度。
- 调用wait(),使该线程处于等待池(wait blocked pool),直到notify()/notifyAll(),线程被唤醒被放到锁定池(lock blocked pool ),释放同步锁使线程回到可运行状态(Runnable)
- 对Running状态的线程加同步锁(Synchronized)使其进入(lock blocked pool ),同步锁被释放进入可运行状态(Runnable)。
此外,在runnable状态的线程是处于被调度的线程,此时的调度顺序是不一定的。Thread类中的yield方法可以让一个running状态的线程转入runnable。
3、 创建线程
(1)方式一:创建Thread子类的一个实例并重写run方法
//创建线程子类,重新run方法public class MyThread extends Thread { public void run(){ System.out.println("MyThread running"); }}//创建线程并执行MyThread myThread = new MyThread();myTread.start();
一旦线程启动后start方法就会立即返回,而不会等待到run方法执行完毕才返回。就好像run方法是在另外一个cpu上执行一样。当run方法执行后,将会打印出字符串MyThread running。
(2)方式二:创建一个Thread的匿名子类
Thread thread = new Thread(){ public void run(){ System.out.println("Thread Running"); }};thread.start();
当新的线程的run方法执行以后,计算机将会打印出字符串”Thread Running”。
(3)方式三:实现Runnable接口
新建一个实现了java.lang.Runnable接口的类的实例,实例中的方法可以被线程调用。
public class MyRunnable implements Runnable { public void run(){ System.out.println("MyRunnable running"); }}
为了使线程能够执行run()方法,需要在Thread类的构造函数中传入 MyRunnable的实例对象。
Thread thread = new Thread(new MyRunnable());thread.start();
当线程运行时,它将会调用实现了Runnable接口的run方法。上例中将会打印出”MyRunnable running”。
(4)方式四:创建一个实现了Runnable接口的匿名类
Runnable myRunnable = new Runnable(){ public void run(){ System.out.println("Runnable running"); }}Thread thread = new Thread(myRunnable);thread.start();
注意:对于这两种方式哪种好并没有一个确定的答案,它们都能满足要求。就我个人意见,我更倾向于实现Runnable接口这种方法。因为线程池可以有效的管理实现了Runnable接口的线程,如果线程池满了,新的线程就会排队等候执行,直到线程池空闲出来为止。而如果线程是通过实现Thread子类实现的,这将会复杂一些。
4、线程同步与锁(synchronized)
Java中的每个对象都有一个监视器,来监测并发代码的重入。在非多线程编码时该监视器不发挥作用,反之如果在synchronized 范围内,监视器发挥作用。
(1)用法一:代码块
在多线程环境下,synchronized块中的方法获取了lock实例的monitor,如果实例相同,那么只有一个线程能执行该块内容。
Thread thread = new Thread(){ public void run(){ System.out.println("Thread Running"); synchronized(lock){..do something } }};thread.start();
(2)用法二:方法
public synchronized int getX() { return x++; }
关于锁和同步,有一下几个要点:
- 只能同步方法,而不能同步变量和类;
- 每个对象只有一个锁;当提到同步时,应该清楚在什么上同步?也就是说,在哪个对象上同步。
- 必同步类中所有的方法,类可以同时拥有同步和非同步方法;
- 如果两个线程要执行一个类中的synchronized方法,并且两个线程使用相同的实例来调用方法,那么一次只能有一个线程能够执行方法,另一个需要等待,直到锁被释放。也就是说:如果一个线程在对象上获得一个锁,就没有任何其他线程可以进入(该对象的)类中的任何一个同步方法;
- 如果线程拥有同步和非同步方法,则非同步方法可以被多个线程自由访问而不受锁的限制;
- 线程睡眠时,它所持的任何锁都不会释放;
- 线程可以获得多个锁。比如,在一个对象的同步方法里面调用另外一个对象的同步方法,则获取了两个对象的同步锁;
- 同步损害并发性,应该尽可能缩小同步范围。同步不但可以同步整个方法,还可以同步方法中一部分代码块;
5、wait()与notify/notifyAll()
wait() 与 notify/notifyAll() 是放在同步代码块中的。当线程执行wait()时,会把当前的锁释放,然后让出CPU,进入等待状态。当执行notify/notifyAll方法时,会唤醒一个处于等待该 对象锁 的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronized修饰的代码块)后再释放锁。从这里可以看出,notify/notifyAll()执行后,并不立即释放锁,而是要等到执行完临界区中代码后,再释放。故,在实际编程中,我们应该尽量在线程调用notify/notifyAll()后,立即退出临界区。即不要在notify/notifyAll()后面再写一些耗时的代码。
6、join()
thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。
t.join(); //使调用线程 t 在此之前执行完毕。t.join(1000); //等待 t 线程,等待时间是1000毫秒
调用t.join时,必须能够拿到线程t对象的锁,如果拿不到它是无法wait的,必须同步锁释放后才调用join方法,才能wait.
**相关链接
如何创建并运行java线程 http://www.importnew.com/20672.html
java线程:线程的同步于锁 http://lavasoft.blog.51cto.com/62575/99155/
JAVA多线程之wait/notify https://www.cnblogs.com/hapjin/p/5492645.html
java多线程中join方法的理解 http://uule.iteye.com/blog/1101994
java中的线程只要看这篇就够了 https://www.cnblogs.com/wxd0108/p/5479442.html
- J2EE-线程
- 【J2EE】--线程介绍
- j2ee的线程安全--threadlocal
- j2ee中每一个线程对应一个session
- J2EE
- J2EE
- J2EE
- J2EE
- J2EE
- J2ee
- j2ee
- J2EE
- J2EE
- j2ee
- J2EE
- J2EE
- j2ee
- J2EE
- 什么是JSP;JSP的模板修改和注释
- table 'mysql.proc' doesn't exist问题解决
- 3D金字塔图(2)
- MySQL(四)源码安装
- 模板:树链剖分
- J2EE-线程
- 7-15(查找) 航空公司VIP客户查询(25 分)
- javascript控制点击一次按钮实现元素的显示隐藏
- 针对移动终端(ARM/Android/TEE)的Rowhammer攻击与电源管理攻击研究
- iOS【NSTimer到底准不准?】
- Linux shell 运算
- SDUT-oj 字符串扩展
- MySQL(五)数据库操作
- 架构师之路:Spring高效开发带前后端开发完整电商平台