1、虽然System.out.println内部是加了锁的,但是如果System.out.println(i- -),依然是线程不安全的,因为有的JVM,i- -需要三步才能完成。
2、通过interrupt方法停止线程
public class IntteruptStop
{
public static void main(String[] args)
{
try
{
MyThread mt = new MyThread();
mt.start();
Thread.sleep(1000);
mt.interrupt();
}
catch(Exception e)
{
}
}
private static class MyThread extends Thread
{
@Override
public void run()
{
for(int i = 0; i < 500000; i++)
{
System.out.println("i = " + (i + 1));
//这里也可以用Thread.interrupted();
if(currentThread().isInterrupted())
{
System.out.println("break");
break;
}
}
//注意,如果这里还有代码,依然会继续执行
}
}
}
3、interrupted方法会清除状态标志,而isInterrupted不会
4、interrupted方法和sleep
public class InterruptSleep
{
public static void main(String[] args)
{
try
{
MyThread mt = new MyThread();
mt.start();
Thread.sleep(1000);
mt.interrupt();
}
catch(Exception e)
{
}
}
private static class MyThread extends Thread
{
@Override
public void run()
{
// for(int i = 0; i < 500000; i++)
// {
// System.out.println("i = " + (i + 1));
// }
try
{
System.out.println(System.currentTimeMillis());
Thread.sleep(5000);
}
catch(InterruptedException e)
{
System.out.println(System.currentTimeMillis());
System.out.println("end");
//这里标志已经被清除成false
System.out.println(isInterrupted());
}
}
}
}
可以理解为sleep方法会时刻检查isInterrupt的值,如果为true就会立刻结束并抛出异常,同时把标志清为false。
5、不要使用stop方法
public class StopError
{
public static void main(String[] args)
{
try
{
SynchronizedObject obj = new SynchronizedObject();
MyThread mt = new MyThread(obj);
mt.start();
Thread.sleep(500);
mt.stop();
System.out.println(obj.getUsername() + ", " + obj.getPassword());
}
catch(Exception e)
{
}
}
private static class SynchronizedObject
{
String username = "a";
String password = "aa";
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
synchronized void printString(String username, String password)
{
try
{
this.username = username;
Thread.sleep(100000);
this.password = password;
}
catch(InterruptedException e)
{
}
catch(ThreadDeath e)
{
System.out.println(e);
}
}
}
private static class MyThread extends Thread
{
SynchronizedObject obj;
public MyThread(SynchronizedObject obj)
{
super();
this.obj = obj;
}
@Override
public void run()
{
obj.printString("b", "bb");
}
}
}
最终输出:
java.lang.ThreadDeath
b, aa
也就是说加了锁的printString方法并未执行完成线程就被强行终止,导致不可预知的错误。
6、不要使用suspend和resume
package com.amuro.studythread.chapter_1_thread;
public class SuspendError
{
public static void main(String[] args)
{
try
{
SynchronizedObject obj = new SynchronizedObject();
Thread t1 = new Thread(new Runnable()
{
@Override
public void run()
{
obj.printString();
}
});
t1.setName("a");
t1.start();
Thread t2 = new Thread(new Runnable()
{
@Override
public void run()
{
obj.printString();
}
});
t2.start();
}
catch(Exception e)
{
e.printStackTrace();
}
}
private static class SynchronizedObject
{
@SuppressWarnings("deprecation")
synchronized void printString()
{
System.out.println(Thread.currentThread().getName() + " : begin");
if(Thread.currentThread().getName().equals("a"))
{
System.out.println(Thread.currentThread().getName() + " : suspend");
Thread.currentThread().suspend();
}
System.out.println(Thread.currentThread().getName() + " : end");
}
}
}
最终输出
a : begin
a : suspend
也就是说如果a线程在使用某同步对象为执行完成时就暂停,会导致该对象在其resume之前永远无法被其他线程访问。
7、yield方法作用是放弃当前CPU使用权,将它让给其他任务来占用CPU执行时间。但放弃的时间不确定,可能刚放弃就又拿到了CPU时间片。
8、线程优先级的特性
1)继承性,A线程中启动B线程,A和B具有一样的优先级;
2)规则性,CPU会尽量把执行资源让给优先级较高的线程;
3)随机性,和2)相关,尽量不代表一定,所以优先级高的未必会比优先级低的先执行完
9、守护线程
package com.amuro.studythread.chapter_1_thread;
public class Daemon
{
public static void main(String[] args)
{
try
{
MyThread mt = new MyThread();
mt.setDaemon(true);
mt.start();
Thread.sleep(5000);
//当进程中不存在非守护线程时,守护线程就被自动销毁
}
catch(Exception e)
{
}
}
private static class MyThread extends Thread
{
int i = 0;
@Override
public void run()
{
while(true)
{
try
{
i++;
System.out.println("i = " + i);
Thread.sleep(1000);
}
catch (Exception e)
{
}
}
}
}
}