1.第一个多线程程序
public class Text {
public static void main(String[] args) {
DoThread();
}
protected static void DoThread(){
final StringBuilder sb=new StringBuilder();
for(int i=0;i<10;i++){
new Thread(){
public void run(){
System.out.println("Java并发");
}
}.start();
}
for(int i=0;i<10;i++){
new Thread(){
@Override
public void run() {
System.out.println("Java编程");
}
}.start();
}
}
}
上面代码通过最简单的方式来创建线程并开始:
new Thread(){
public void run(){
System.out.println("Java并发");
}
}.start();
类似大家可以通过其他的方式来代替上面的部分(Runnable方式等)
下面是运行结果:
2.查看线程的运行状态
public class Text {
public static void main(String[] args) throws InterruptedException{
ThreadState state = new ThreadState();//新建任务对象
Thread thread = new Thread(state);//新建一个线程
System.out.println("新建线程:"+thread.getState());
thread.start();//让线程开始
System.out.println("启动线程:"+thread.getState());
Thread.sleep(100);//使线程睡眠0.1s
System.out.println("计时等待"+thread.getState());
Thread.sleep(1000);//使线程睡眠1s
System.out.println("等待线程"+thread.getState());
state.notifyNow();//唤醒该线程
System.out.println("唤醒线程"+thread.getState());
Thread.sleep(1000);//又使线程睡眠1s
System.out.println("线程终止:"+thread.getState());
}
}
class ThreadState implements Runnable{//自定义任务
//使执行此任务的线程等待0.5秒
public synchronized void waitForASecond() throws InterruptedException{
wait(500);
}
//使执行此任务的线程无限等待
public synchronized void waitForYears() throws InterruptedException{
wait();
}
//唤醒执行此任务的线程
public synchronized void notifyNow() throws InterruptedException{
notify();
}
@Override
public void run() {
try{
waitForASecond();//让线程等待0.5秒
waitForYears();//让线程等待
for (int i=0;i<10000;i++){
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
下面我们解析上面代码的主方法运行过程:
首先主线程开始,给主方法分配栈帧
然后新建任务对象和子线程对象放到堆中,此时子线程thread处于新建状态NEW
所以第一个输出语句 打印的是: 新建线程: NEW
然后调用start()方法让线程thread启动,启动后的线程的状态为RUNNABLE,所以后面打印的是: 启动线程:RUNNABLE
注意后面调用的是sleep()让main线程处于睡眠状态0.5s,之后,子线程运行waitForASecoond()处于计时等待状态,所以后面打印的是: 计时等待:TIMED_WAITING
之后又让mian线程睡眠1s,此时子线程的计时等待以及结束,进入下面的无限等待状态,所以下面的打印信息为:
等待线程WAITING
然后,主线程调用任务对象的notifyNow()方法来唤醒子线程,所以下面打印:唤醒线程:RUNNABLE
之后主线程等待1秒,子线程结束,此时打印:线程终止:TERMINATED
运行结果:
3.查看JVM中的线程名
要实现这个功能我们需要用到ThreadGroup这个API, ThreadGroup表示一个线程的集合,此外,线程组也可以包含其他线程组,所以线程组可以构成一棵树,在树中,除了初始线程组外,每个线程都有一个父线程组。 我们允许线程访问有关自己的线程组的信息,但不允许它访问有关其他线程组的父线程组或者其他线程组的信息。
这个类的常用方法有:
方法名 | 作用 |
---|---|
activeCount() | 返回此线程组中的活动线程的估计数 |
activeGroupCount() | 返回此线程组中活动线程组的估计数 |
enumerate(Thread[] list,boolean recurse) | 把此线程组中的所有活动线程复制到指定数组中 |
enumerate(ThreadGroup[] list,boolean recurse) | 把对此线程组中的所有活动子组的引用复制到指定数组中 |
getName() | 返回此线程组的名称 |
getParent() | 返回此线程组的父线程组 |
public class Text {
public static void main(String[] args) throws InterruptedException{
for (String string:getThreadGroups(getRootThreadGroup())){
System.out.println(string);
}
}
//获得根线程组
private static ThreadGroup getRootThreadGroup(){
ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
while(true){
if(rootGroup.getParent()!=null){
rootGroup = rootGroup.getParent();
}else{
break;
}
}
return rootGroup;
}
//获取活跃线程列表
public static List<String> getThreads(ThreadGroup group){
List<String> threadList = new ArrayList<String>();//新建一个列表
Thread[] threads = new Thread[group.activeCount()];//建立活跃线程数组
int count = group.enumerate(threads,false);//将活跃的线程复制到threads数组中
for(int i=0;i<count;i++){
threadList.add(group.getName()+"线程组:"+threads[i].getName());//将线程名逐个添加到线程列表中
}
return threadList;//返回线程列表
}
//获取线活跃程组列表
public static List<String> getThreadGroups(ThreadGroup group){
List<String> threadList = getThreads(group);
ThreadGroup[] groups = new ThreadGroup[group.activeGroupCount()];
int count = group.enumerate(groups,false);
for(int i=0;i<count;i++){
threadList.addAll(getThreads(groups[i]));
}
return threadList;
}
}