标签:java Thread yield 死锁 线程 优先级 多线程 方法
1.进程和线程
进程 一个在内存中运行的程序,它有一块独立的内存空间
线程 存在于进程中,是一个进程中的一条执行线索,同一个进程中可以有多个线程,线程可以并发运行
2.用 Thread 类创建线程
1) 设计一个类,要继承 Thread 类
2) 重写run方法
3) new 这个类的对象
4) 调用 start() 方法启动这个线程, start() 方法有两个层面的含义, 一是启动线程,二是调用线程中的run() 方法
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread thread =new MyThread();
thread.start();
while(true){
System.out.println("线程:"+Thread.currentThread().getName() + " -> -> ->");
}
}
}
class MyThread extends Thread{
MyThread(String name){ //可以用这样的方式给线程设置名称
setName(name);
//super(name);
}
public void run() {
while(true){
System.out.println("线程:"+getName()+" (- (- (-");
}
}
}
3.线程的状态
新建 (Born) : 新建的线程处于新建状态
就绪 (Ready) : 在创建线程后,start() 方法被调用它将处于就绪状态
运行 (Running) : 线程在开始执行时(run)进入运行状态
睡眠 (Sleeping) : 线程的执行可通过使用 sleep() 方法来暂时中止。在睡眠后,线程将进入就绪状态
等待 (Waiting) : 如果调用了 wait() 方法,线程将处于等待状态。用于在两个或多个线程并发运行时。
挂起 (Suspended) : 在临时停止或中断线程的执行时,线程就处于挂起状态。 //suspend() 已过时,有固定的死锁倾向
恢复 (Resume) : 在挂起的线程被恢复执行时,可以说它已被恢复。
阻塞 (Blocked) – 在线程等待一个事件时(例如输入/输出操作),就称其处于阻塞状态。
死亡 (Dead) – 在 run() 方法已完成执行或其 stop() 方法被调用之后,线程就处于死亡状态。 //stop 方法有两个重载,均已过时,有固定的不安全性
线程的暂停
==线程优先级比较低,因此它不能获得 CPU 时间
==使用 sleep( ) 方法使线程睡眠。
==通过调用 wait( ) 方法,使线程等待。
==通过调用 yield ( ) 方法,线程显式出让CPU控制权
==线程由于等待一个文件I/O事件被阻塞
附 : sleep 和 yield 的区别
1) sleep是Thread类的一个静态方法,该方法会让当前正在 执行的线程暂停执行,从而将执行机会让给其他线程执行。
sleep(long mills)参数指定当前线程暂停执行的时间,经过这段阻塞时间后,该线程会进入就绪状态,等候线程调度器的调度
sleep方法声明抛出了InterruptedException异常,所以调用sleep方法时要么在方法开始处抛出异常要么使用try{}..catch{}块进行捕获。
2) yield方法只会给优先级相同或更高优先级的线程执行机会。yield不会将线程转入阻塞状态,只是强制当前线程进入就绪状态。
因此完全有可能某个线程调用yield方法暂停后,立即又获得处理器资源被执行。yield方法没有声明抛出任何异常。
// 通俗地说 yield()方法只是把线程的状态由执行状态打回准备就绪状态
... 某个线程类的run方法
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println(getName() + "--->" + i);
if (i == 20) {
Thread.yield();
}
}
}
public static void main(String[] args) {
YieldThread t1 = new YieldThread("高级");
t1.start();
// 若当前线程优先级最高,那么即使调用了yield()方法,线程调度器又会将这个线程调度出来重新执行
// t1.setPriority(Thread.MAX_PRIPORITY);
YieldThread t2 = new YieldThread("低级");
t2.start();
t2.setPriority(Thread.MIN_PRIORITY);
}
Java 中的线程优先级是在 Thread 类中定义的常量
NORM_PRIORITY : 值为 5
MAX_PRIORITY : 值为 10
MIN_PRIORITY : 值为 1
缺省优先级为 NORM_PRIORITY
有关优先级的方法有两个:
final void setPriority(int newp) : 修改线程的当前优先级
final int getPriority() : 返回线程的优先级
4.synchronized(同步锁)
synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。它包括两种用法:synchronized 方法和 synchronized 块。
5.使用Runable接口实现多线程
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread m=new MyThread();
Thread th=new Thread(m);
th.start();
while(true){
System.out.println("--------->");
}
}
}
//实现 Runnable 接口
class MyThread implements Runnable {
public void run() {
while(true){
System.out.println("(------------");
}
}
}
使用继承Thread类和实现Runnable方式实现线程,有什么区别?
1) 使用后者,更容易实现多个线程之间的数据共享
2) 可以避免java中不支持多继承带来的问题
9.死锁
死锁是两个或更多线程阻塞着等待其它处于死锁状态的线程所持有的锁。死锁通常发生在多个线程同时但以不同的顺序请求同一组锁的时候。
例如,如果线程1锁住了A,然后尝试对B进行加锁,同时线程2已经锁住了B,接着尝试对A进行加锁,这时死锁就发生了。线程1永远得不到B,线程2也永远得不到A,并且它们永远也不会知道发生了这样的事情。为了得到彼此的对象(A和B),它们将永远阻塞下去。这种情况就是一个死锁。
java中,解决死锁一般有如下方法:
1)尽量使用tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),设置超时时间,超时可以退出防止死锁。
2)尽量使用java.util.concurrent(jdk 1.5以上)包的并发类代替手写控制并发,比较常用的是ConcurrentHashMap、ConcurrentLinkedQueue、AtomicBoolean等等,实际应用中java.util.concurrent.atomic十分有用,简单方便且效率比使用Lock更高
3)尽量降低锁的使用粒度,尽量不要几个功能用同一把锁
4)尽量减少同步的代码块
标签:java,Thread,yield,死锁,线程,优先级,多线程,方法 来源: https://blog.csdn.net/weixin_37909789/article/details/94556191
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。