1.线程的状态
public enum State {
/**
* The thread has been created, but has never been started.
*/
NEW,
/**
* The thread may be run.
*/
RUNNABLE,
/**
* The thread is blocked and waiting for a lock.
*/
BLOCKED,
/**
* The thread is waiting.
*/
WAITING,
/**
* The thread is waiting for a specified amount of time.
*/
TIMED_WAITING,
/**
* The thread has been terminated.
*/
TERMINATED
}
1.1NEW RUNNABLE TERMINATED
public class MyThread extends Thread {
public MyThread() {
//构造方法是被主线程调用的,因此这里的状态是主线程的状态
System.out.println("构造方法中的状态:" + Thread.currentThread().getState());
}
@Override
public void run() {
System.out.println("run方法中的状态:" + Thread.currentThread().getState());
}
}
public class Run {
// NEW,
// RUNNABLE,
// TERMINATED,
// BLOCKED,
// WAITING,
// TIMED_WAITING,
public static void main(String[] args) {
try {
MyThread t = new MyThread();
System.out.println("main方法中的状态1:" + t.getState());
Thread.sleep(1000);
t.start();
Thread.sleep(1000);
System.out.println("main方法中的状态2:" + t.getState());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
构造方法中的状态:RUNNABLE//构造方法是由主线程调用的,因此这里的状态是主线程的状态
main方法中的状态1:NEW
run方法中的状态:RUNNABLE
main方法中的状态2:TERMINATED
1.2 TIME_WAITING
public class MyThread extends Thread {
@Override
public void run() {
try {
System.out.println("begin sleep");
Thread.sleep(10000);
System.out.println(" end sleep");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
try {
MyThread t = new MyThread();
t.start();
Thread.sleep(1000);
System.out.println("main方法中的状态:" + t.getState());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:
begin sleep
main方法中的状态:TIMED_WAITING
end sleep
1.3 BLOCKED出现在某一个线程正在等待锁的时候
1.4 WAITING 线程执行了wait()方法后的状态
public class Lock {
public static final Byte lock = new Byte("0");
}
public class MyThread extends Thread {
@Override
public void run() {
try {
synchronized (Lock.lock) {
Lock.lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
try {
MyThread t = new MyThread();
t.start();
Thread.sleep(1000);
System.out.println("main方法中的t状态:" + t.getState());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:
main方法中的t状态:WAITING
2.线程组
线程组中可以有线程对象也可以有线程组
2.1线程对象关联线程组:1级关联
public class ThreadA extends Thread {
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
System.out
.println("ThreadName=" +
Thread.currentThread().
getName());
Thread.sleep(3000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class ThreadB extends Thread {
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
System.out
.println("ThreadName=" +
Thread.currentThread().
getName());
Thread.sleep(3000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
ThreadA aRunnable = new ThreadA();
ThreadB bRunnable = new ThreadB();
ThreadGroup group = new ThreadGroup("高洪岩的线程组");
Thread aThread = new Thread(group, aRunnable);
Thread bThread = new Thread(group, bRunnable);
aThread.start();
bThread.start();
System.out.println("活动的线程数为:" + group.activeCount());
System.out.println("线程组的名称为:" + group.getName());
}
}
运行结果:
ThreadName=Thread-2
ThreadName=Thread-3
活动的线程数为:2
线程组的名称为:高洪岩的线程组
ThreadName=Thread-2
ThreadName=Thread-3
ThreadName=Thread-2
ThreadName=Thread-3
2.2线程对象关联线程组 :多级关联
public class Run {
public static void main(String[] args) {
// 在main组中添加一个线程组A,然后在这个A组中添加线程对象Z
// 方法activeGroupCount()和activeCount()的值不是固定的
// 是系统中环境的一个快照
ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
ThreadGroup group = new ThreadGroup(mainGroup, "A");
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
System.out.println("runMethod!");
Thread.sleep(10000);// 线程必须在运行状态才可以受组管理
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Thread newThread = new Thread(group, runnable);
newThread.setName("Z");
newThread.start();// 线程必须启动然后才归到组A中
// ///
ThreadGroup[] listGroup = new ThreadGroup[Thread.currentThread()
.getThreadGroup().activeGroupCount()];
Thread.currentThread().getThreadGroup().enumerate(listGroup);
System.out.println("main线程中有多少个子线程组:" + listGroup.length + " 名字为:"
+ listGroup[0].getName());
Thread[] listThread = new Thread[listGroup[0].activeCount()];
listGroup[0].enumerate(listThread);
System.out.println(listThread[0].getName());
}
}
2.3线程组自动归属特性
自动归属就是自动归到当前线程组中
public class Run {
public static void main(String[] args) {
System.out.println("A处线程:"+Thread.currentThread().getName()+" 中有线程组数量:"+Thread.currentThread().getThreadGroup().activeGroupCount());
ThreadGroup group=new ThreadGroup("新的组");
System.out.println("A处线程:"+Thread.currentThread().getName()+" 中有线程组数量:"+Thread.currentThread().getThreadGroup().activeGroupCount());
ThreadGroup[] threadGroup=new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];
Thread.currentThread().getThreadGroup().enumerate(threadGroup);
for (int i = 0; i < threadGroup.length; i++) {
System.out.println("第一个线程组名称为:"+threadGroup[i].getName());
}
}
}
运行结果;
A处线程:main 中有线程组数量:0
A处线程:main 中有线程组数量:1
第一个线程组名称为:新的组
2.4获取根线程组
public class Run {
public static void main(String[] args) {
System.out.println("线程:" + Thread.currentThread().getName()
+ " 所在的线程组名为:"
+ Thread.currentThread().getThreadGroup().getName());
System.out
.println("main线程所在的线程组的父线程组的名称是:"
+ Thread.currentThread().getThreadGroup().getParent()
.getName());
System.out.println("main线程所在的线程组的父线程组的父线程组的名称是:"
+ Thread.currentThread().getThreadGroup().getParent()
.getParent().getName());
}
}
运行结果:jvm的根线程组就是system
线程:main 所在的线程组名为:main
main线程所在的线程组的父线程组的名称是:system
Exception in thread "main" java.lang.NullPointerException
at test.run.Run.main(Run.java:15)
2.5线程组里添加线程组
public class Run {
public static void main(String[] args) {
System.out.println("线程组名称:"
+ Thread.currentThread().getThreadGroup().getName());
System.out.println("线程组中活动的线程数量:"
+ Thread.currentThread().getThreadGroup().activeCount());
System.out.println("线程组中线程组的数量-加之前:"
+ Thread.currentThread().getThreadGroup().activeGroupCount());
ThreadGroup newGroup = new ThreadGroup(Thread.currentThread()
.getThreadGroup(), "newGroup");
System.out.println("线程组中线程组的数量-加之之后:"
+ Thread.currentThread().getThreadGroup().activeGroupCount());
System.out
.println("父线程组名称:"
+ Thread.currentThread().getThreadGroup().getParent()
.getName());
}
}
运行结果:
线程组名称:main
线程组中活动的线程数量:1
线程组中线程组的数量-加之前:0
线程组中线程组的数量-加之之后:1
父线程组名称:system
2.6组内的线程批量停止
public class MyThread extends Thread {
public MyThread(ThreadGroup group, String name) {
super(group, name);
}
@Override
public void run() {
System.out.println("ThreadName=" + Thread.currentThread().getName()
+ "准备开始死循环了:)");
while (!this.isInterrupted()) {
}
System.out.println("ThreadName=" + Thread.currentThread().getName()
+ "结束了:)");
}
}
public class Run {
public static void main(String[] args) {
try {
ThreadGroup group = new ThreadGroup("我的线程组");
for (int i = 0; i < 5; i++) {
MyThread thread = new MyThread(group, "线程" + (i + 1));
thread.start();
}
Thread.sleep(5000);
group.interrupt();
System.out.println("调用了interrupt()方法");
} catch (InterruptedException e) {
System.out.println("停了停了!");
e.printStackTrace();
}
}
}
运行结果:
ThreadName=线程1准备开始死循环了:)
ThreadName=线程5准备开始死循环了:)
ThreadName=线程4准备开始死循环了:)
ThreadName=线程3准备开始死循环了:)
ThreadName=线程2准备开始死循环了:)
调用了interrupt()方法
ThreadName=线程3结束了:)
ThreadName=线程1结束了:)
ThreadName=线程5结束了:)
ThreadName=线程4结束了:)
ThreadName=线程2结束了:)
3.有序运行
public class MyThread extends Thread {
private Object lock;
private String showChar;
private int showNumPosition;
private int printCount = 0;// 统计打印了几个字母
volatile private static int addNumber = 1;
public MyThread(Object lock, String showChar, int showNumPosition) {
super();
this.lock = lock;
this.showChar = showChar;
this.showNumPosition = showNumPosition;
}
@Override
public void run() {
try {
synchronized (lock) {
while (true) {
if (addNumber % 3 == showNumPosition) {
System.out.println("ThreadName="
+ Thread.currentThread().getName()
+ " runCount=" + addNumber + " " + showChar);
lock.notifyAll();
addNumber++;
printCount++;
if (printCount == 3) {
break;
}
} else {
lock.wait();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
Object lock = new Object();
MyThread a = new MyThread(lock, "A", 1);
MyThread b = new MyThread(lock, "B", 2);
MyThread c = new MyThread(lock, "C", 0);
a.start();
b.start();
c.start();
}
}
运行结果:
ThreadName=Thread-0 runCount=1 A
ThreadName=Thread-1 runCount=2 B
ThreadName=Thread-2 runCount=3 C
ThreadName=Thread-0 runCount=4 A
ThreadName=Thread-1 runCount=5 B
ThreadName=Thread-2 runCount=6 C
ThreadName=Thread-0 runCount=7 A
ThreadName=Thread-1 runCount=8 B
ThreadName=Thread-2 runCount=9 C
4.SimpleDateFormat非线程安全
4.1错误
public class MyThread extends Thread {
private SimpleDateFormat sdf;
private String dateString;
public MyThread(SimpleDateFormat sdf, String dateString) {
super();
this.sdf = sdf;
this.dateString = dateString;
}
@Override
public void run() {
try {
Date dateRef = sdf.parse(dateString);
String newDateString = sdf.format(dateRef).toString();
if (!newDateString.equals(dateString)) {
System.out.println("ThreadName=" + this.getName()
+ "报错了 日期字符串:" + dateString + " 转换成的日期为:"
+ newDateString);
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}
public class Test {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String[] dateStringArray = new String[] { "2000-01-01", "2000-01-02",
"2000-01-03", "2000-01-04", "2000-01-05", "2000-01-06",
"2000-01-07", "2000-01-08", "2000-01-09", "2000-01-10" };
MyThread[] threadArray = new MyThread[10];
for (int i = 0; i < 10; i++) {
threadArray[i] = new MyThread(sdf, dateStringArray[i]);
}
for (int i = 0; i < 10; i++) {
threadArray[i].start();
}
}
}
运行结果:
ThreadName=Thread-2报错了 日期字符串:2000-01-03 转换成的日期为:2000-01-02
ThreadName=Thread-4报错了 日期字符串:2000-01-05 转换成的日期为:2000-01-01
ThreadName=Thread-6报错了 日期字符串:2000-01-07 转换成的日期为:1970-01-07
4.1解决方式1
public class MyThread extends Thread {
private SimpleDateFormat sdf;
private String dateString;
public MyThread(SimpleDateFormat sdf, String dateString) {
super();
this.sdf = sdf;
this.dateString = dateString;
}
@Override
public void run() {
try {
Date dateRef = DateTools.parse("yyyy-MM-dd", dateString);
String newDateString = DateTools.format("yyyy-MM-dd", dateRef)
.toString();
if (!newDateString.equals(dateString)) {
System.out.println("ThreadName=" + this.getName()
+ "报错了 日期字符串:" + dateString + " 转换成的日期为:"
+ newDateString);
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}
public class DateTools {
public static Date parse(String formatPattern, String dateString)
throws ParseException {
return new SimpleDateFormat(formatPattern).parse(dateString);
}
public static String format(String formatPattern, Date date) {
return new SimpleDateFormat(formatPattern).format(date).toString();
}
}
public class Test {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String[] dateStringArray = new String[] { "2000-01-01", "2000-01-02",
"2000-01-03", "2000-01-04", "2000-01-05", "2000-01-06",
"2000-01-07", "2000-01-08", "2000-01-09", "2000-01-10" };
MyThread[] threadArray = new MyThread[10];
for (int i = 0; i < 10; i++) {
threadArray[i] = new MyThread(sdf, dateStringArray[i]);
}
for (int i = 0; i < 10; i++) {
threadArray[i].start();
}
}
}
4.2解决方式2
public class DateTools {
private static ThreadLocal<SimpleDateFormat> tl = new ThreadLocal<SimpleDateFormat>();
public static SimpleDateFormat getSimpleDateFormat(String datePattern) {
SimpleDateFormat sdf = null;
sdf = tl.get();
if (sdf == null) {
sdf = new SimpleDateFormat(datePattern);
tl.set(sdf);
}
return sdf;
}
}
public class MyThread extends Thread {
private SimpleDateFormat sdf;
private String dateString;
public MyThread(SimpleDateFormat sdf, String dateString) {
super();
this.sdf = sdf;
this.dateString = dateString;
}
@Override
public void run() {
try {
Date dateRef = DateTools.getSimpleDateFormat("yyyy-MM-dd").parse(
dateString);
String newDateString = DateTools.getSimpleDateFormat("yyyy-MM-dd")
.format(dateRef).toString();
if (!newDateString.equals(dateString)) {
System.out.println("ThreadName=" + this.getName()
+ "报错了 日期字符串:" + dateString + " 转换成的日期为:"
+ newDateString);
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}
public class Test {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String[] dateStringArray = new String[] { "2000-01-01", "2000-01-02",
"2000-01-03", "2000-01-04", "2000-01-05", "2000-01-06",
"2000-01-07", "2000-01-08", "2000-01-09", "2000-01-10" };
MyThread[] threadArray = new MyThread[10];
for (int i = 0; i < 10; i++) {
threadArray[i] = new MyThread(sdf, dateStringArray[i]);
}
for (int i = 0; i < 10; i++) {
threadArray[i].start();
}
}
}
网友评论