1.主线程结束以后并不是虚拟机就立刻退出进程,还要执行其他的线程,在主线程执行结束之后就要清除整个所占的内存空间。
2.java虚拟机的垃圾回收的随机进行的,所以在一定的程度上无法控制程序的运行(不是堆内存中一产生垃圾就清除)
3.创建新的线程来同时运行多部分代码
创建新线程有两种方法:
<1>继承Thread类
定义一个类继承Thread类
覆盖Thread类中的run方法
直接创建Thread的子类对象(线程)
启动线程调用start方法
示例代码:
public class NewThread
{
public static void main(String[] args)
{
Demo d1 = new Demo("大概率石乐志123");
Demo d2 = new Demo("李时珍");
//创建Thread的子类对象
d1.start();
d2.start();
//启动线程
}
}
class Demo extends Thread //继承线程Thread子类
{
private String name;
Demo(String name)
{
this.name = name;
}
public void run()//复写run方法体
{
for(int i = 1;i < 10; i++)
{
for(int j = -10000000;j < 10000000;j++)
{}
System.out.println(name+"...."+i);
}
} /*public void show()
{
for(int i = 1;i < 100000; i++)
System.out.println(name+"...."+i);
}
*/可以直接在run方法中写函数名,也可以将函数体写到run方法体中
}
运行结果:
李时珍….1
大概率石乐志123….1
李时珍….2
大概率石乐志123….2
李时珍….3
大概率石乐志123….3
大概率石乐志123….4
大概率石乐志123….5
大概率石乐志123….6
大概率石乐志123….7
大概率石乐志123….8
大概率石乐志123….9
李时珍….4
李时珍….5
李时珍….6
李时珍….7
李时珍….8
李时珍….9
<2>获取线程的名称
调用Thread子类的getName()方法
调用当前线程的对象 Thread.currenThread()
示例代码:
System.out.println(name+".."+i+"+" ThreadName="+getName());
运行结果:
李时珍….1 ThreadName=Thread-1
李时珍….2 ThreadName=Thread-1
大概率石乐志123….1 ThreadName=Thread-0
大概率石乐志123….2 ThreadName=Thread-0
大概率石乐志123….3 ThreadName=Thread-0
大概率石乐志123….4 ThreadName=Thread-0
大概率石乐志123….5 ThreadName=Thread-0
大概率石乐志123….6 ThreadName=Thread-0
大概率石乐志123….7 ThreadName=Thread-0
大概率石乐志123….8 ThreadName=Thread-0
大概率石乐志123….9 ThreadName=Thread-0
李时珍….3 ThreadName=Thread-1
李时珍….4 ThreadName=Thread-1
李时珍….5 ThreadName=Thread-1
李时珍….6 ThreadName=Thread-1
李时珍….7 ThreadName=Thread-1
李时珍….8 ThreadName=Thread-1
李时珍….9 ThreadName=Thread-1
注:
jvm创建的主线程都在主函数中,而自定义的线程的任务是被封装在run方法中(run方法中有要运行的任务代码)*
<3>实现Runnable接口
*定义类实现Runnable接口
*覆盖接口中的run方法,将县城任务代码封装在run方法中
*通过Thread类来创建线程对象,并将Runnable接口的子类对象作为Thread类的构造器的参数进行传递(就是将你新定义好的对象放到构造器中)
*调用线程对象的start方法开启线程
示例代码:
public class TextRunnable
{
public static void main(String[] args)
{
Demo3 d1 = new Demo3(); //不是线程对象
Demo3 d2 = new Demo3();
Thread t1 = new Thread(d1);
Thread t2 = new Thread(d2);
t1.start();
t2.start();
}
}
class Demo3 implements Runnable //扩展demo类的内容燃气中的代码作为线程的任务来执行
{
public void run()
{
show();
}
public void show()
{
for(int i = 1;i < 5; i++)
System.out.println(Thread.currentThread().getName()+"..."+i);
}
}
运行结果:
Thread-0…1
Thread-1…1
Thread-0…2
Thread-1…2
Thread-1…3
Thread-1…4
Thread-0…3
Thread-0…4
*注:
线程要实现的任务代码都封装在Runnable接口的run 方法中,所以在创建线程的时候就要明确任务对象(就是传递参数)*
4.线程的状态
CPU执行资格:可以被CPU所处理。在处理队列中排队
CPU执行权:正在被CPU处理
<1>被创建 start()
<2>运行状态run()
<3>消亡状态 线程自然的结束,调用函数stop()
<4>冻结状态:
睡眠状态
sleep(time) //线程失去CPU执行资格和执行权,然后在时间结束之后自动的加入队列
等待状态
wait() //线程失去CPU的执行资格和执行权,也没有时间限制
notify() //对正在等待的线程进行唤醒
<5>临时阻塞状态
是指线程具有执行资格但是没有执行权,这个不需要进行调用,因为在CPU的执行过程中每一个线程都是在运行状态与临时阻塞状态之间频繁切换(切换的速度非常快)