正文
java进程阻塞代码 java 实现阻塞队列
小程序:扫一扫查出行
【扫一扫了解最新限行尾号】
复制小程序
【扫一扫了解最新限行尾号】
复制小程序
Java Thread BLOCKED和WAITING两种状态的区别
一、线程5种状态
新建状态(New) 新创建了一个线程对象。
就绪状态(Runnable) 线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
运行状态(Running) 就绪状态的线程获取了CPU,执行程序代码。
阻塞状态(Blocked) 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
二、Jstack中常见的线程状态
应用程序启动后,我们对系统运行状况的观测大部分情况下是通过运行日志。但是若某一天发现,日志中记录的行为与预想的不一致,此时需要进一步的系统监控该怎么办,Jstack是常用的排查工具,它能输出在某一个时间,Java进程中所有线程的状态,很多时候这些状态信息能给我们的排查工作带来有用的线索。
Jstack的输出中,Java线程状态主要是以下几种:
RUNNABLE 线程运行中或I/O等待
BLOCKED 线程在等待monitor锁(synchronized关键字)
TIMED_WAITING 线程在等待唤醒,但设置了时限
WAITING 线程在无限等待唤醒
1) 让线程一直处于RUNNABLE
public static void runnable() {
long i = 0;
while (true) {
i++;
}
}
2) 让线程一直处于BLOCKED
public static void blocked() {
final Object lock = new Object();
new Thread() {
public void run() {
synchronized (lock) {
System.out.println("i got lock, but don't release");
try {
Thread.sleep(1000L * 1000);
} catch (InterruptedException e) {
}
}
}
}.start();
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock) {
try {
Thread.sleep(30 * 1000);
} catch (InterruptedException e) {
}
}
}
主线程sleep,先让另外一个线程拿到lock,并长期持有lock(sleep会持有锁,wait不会)。此时主线程会BLOCK住等待lock被释放,此时jstack的输出可以看到main线程状态是BLOCKED。这里要注意的是只有synchronized这种方式的锁(monitor锁)才会让线程出现BLOCKED状态,等待ReentrantLock则不会。
3) 让线程处于TIMED_WAITING状态
public static void timedWaiting() {
final Object lock = new Object();
synchronized (lock) {
try {
lock.wait(30 * 1000);
} catch (InterruptedException e) {
}
}
}
4)让线程处于WAITING状态
public static void waiting() {
final Object lock = new Object();
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
}
}
}
无超时的等待,必须等待lock.notify()或lock.notifyAll()或接收到interrupt信号才能退出等待状态。
java中多线程使用lock锁 其中一个使用unlock方法为什么锁就失效了
Java中Lock,tryLock,lockInterruptibly的区别如下:
一、 lock()方法
使用lock()获取锁,若获取成功,标记下是该线程获取到了锁(用于锁重入),然后返回。若获取失败,这时跑一个for循环,循环中先将线程阻塞放入等待队列,当被调用signal()时线程被唤醒,这时进行锁竞争(因为默认使用的是非公平锁),如果此时用CAS获取到了锁那么就返回,如果没获取到那么再次放入等待队列,等待唤醒,如此循环。其间就算外部调用了interrupt(),循环也会继续走下去。一直到当前线程获取到了这个锁,此时才处理interrupt标志,若有,则执行 Thread.currentThread().interrupt(),结果如何取决于外层的处理。lock()最终执行的方法如下:
[java] view plain copy
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head tryAcquire(arg)) { //如果竞争得到了锁
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted; //获取成功返回interrupted标志
}
// 只修改标志位,不做其他处理
if (shouldParkAfterFailedAcquire(p, node) parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
其中parkAndCheckInterrupt()调用了LockSupport.park(),该方法使用Unsafe类将进程阻塞并放入等待队列,等待唤醒,和await()有点类似。
可以看到循环中检测到了interrupt标记,但是仅做 interrupted = true 操作,直到获取到了锁,才return interrupted,然后处理如下
[java] view plain copy
public final void acquire(int arg) {
if (!tryAcquire(arg) acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt(); // 执行Thread.currentThread().interrupt()
}
二、 lockInterruptibly()方法
和lock()相比,lockInterruptibly()只有略微的修改,for循环过程中,如果检测到interrupt标志为true,则立刻抛出InterruptedException异常,这时程序变通过异常直接返回到最外层了,又外层继续处理,因此使用lockInterruptibly()时必须捕捉异常。lockInterruptibly()最终执行的方法如下:
[java] view plain copy
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return; //获取成功返回
}
if (shouldParkAfterFailedAcquire(p, node)
parkAndCheckInterrupt())
throw new InterruptedException(); //直接抛出异常
}
} finally {
if (failed)
cancelAcquire(node);
}
}
三、 tryLock()方法
使用tryLock()尝试获取锁,若获取成功,标记下是该线程获取到了锁,然后返回true;若获取失败,此时直接返回false,告诉外层没有获取到锁,之后的操作取决于外层,代码如下:
[java] view plain copy
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
这段java程序问题出在哪里?可以编译出class文件,但是运行时总是有异常,不能运行,怎么解决?代码如下
tf1, tf2;
空值java进程阻塞代码,未指向实例java进程阻塞代码,报空指针异常
package com.neo.brickhome;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class MyFrame implements ActionListener {
JFrame frame = new JFrame("My JFrame");
JButton b1, b2, b3;
JLabel label1, label2;
JTextField tf1, tf2;
public static void main(String[] args) {
MyFrame mf = new MyFrame();
mf.go();
}
public void go() {
label1 = new JLabel("Source");
label2 = new JLabel("Target");
JPanel p3 = new JPanel(new GridLayout(2, 1));
p3.add(label1);
p3.add(label2);
JPanel p4 = new JPanel(new GridLayout(2, 1));
tf1 = new JTextField();
tf2 = new JTextField();
p4.add(tf1);
p4.add(tf2);
JPanel p1 = new JPanel(new GridLayout(1, 2));
p1.add(p3);
p1.add(p4);
JPanel p2 = new JPanel(new FlowLayout());
b1 = new JButton("Clear");
b1.addActionListener(this);
b2 = new JButton("Copy");
b2.addActionListener(this);
b3 = new JButton("Close");
b3.addActionListener(this);
p2.add(b1);
p2.add(b2);
p2.add(b3);
Container cp = frame.getContentPane();
cp.add(p1, BorderLayout.CENTER);
cp.add(p2, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 200);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
if (button == b1) {
tf1.setText(" ");
tf2.setText(" ");
}
if (button == b2) {
if (tf1.getSelectedText() != null)
tf2.setText(tf1.getSelectedText());
else
tf1.setText(tf1.getText());
}
if (button == b3)
System.exit(0);
}
}
就OK
java中进程怎么强制运行,还有死锁的解释
看了你的程序,确实会出现死锁,因为:
1。funA中有需要等待当前线程结束(你的例子中就是主线程)再执行b.last(),此时主线程持有对象a的锁。
2。funB中需要调用a.last()时又需要得到对象a的锁(因为函数声明为synchronized),由于第一点,所以在funcA返回前得不到对象a的锁
3。而funcA要像返回,又必须要调用funcB的线程返回(显然不可能),
所以,你的两个线程死锁了。
对于你的注释中有几中情况下又不死锁了,是因为这样:
1.去掉synchronized关键字,这样last不是同步方法,调用它不需要获得锁,所以……(你知道的)
2.funcA(new B()),或funcB(new A()),实际上都已经新创建了对象了,所以连个线程等待的锁也就不一样了(等待的是不同A(或B)对象的锁),这样当然也不会死锁了。
另外:
//我不太明白你的“进行强制运行”是什么意思,join通常的讲就是等待线程结束后才返回,这应该是借用的LINUX系统的一个术语。
try
{
System.out.println(name+" 进行强制运行");
Thread.currentThread().join();
System.out.println(name+" 进行强制运行");
}
catch(Exception e)
{
System.out.println(name+" 出现异常"+e);
}
关于java进程阻塞代码和java 实现阻塞队列的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。