java线程与进程学习1
前言
进程
进程是计算机中执行的程序;但不仅仅表示代码段和文本段,还包含:
1、当前活动,如程序计数器的值和处理器寄存器的内容等。
2、进程堆栈(包括临时数据,如函数参数、返回地址和局部变量)和数据段(包括全局变量)。
3、堆,进程运行时动态分配的内存。
线程
线程可以看出是一个轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器,线程切换的开销小。
换句话说,线程是一个程序里面不同的执行路径。
一、程序的执行
程序的执行:首先把程序的代码放到内存的代码区里面,代码放到代码区后并没有马上开始执行,但这时候说明了一个进程准备开始,进程已经产生了,但还没有开始执行,这就是进程,所以进程其实是一个静态的概念,它本身就不能动。平常所说的进程的执行指的是进程里面主线程
开始执行了,也就是main()方法
开始执行了。进程是一个静态的概念,在我们机器里面实际上运行的都是线程
。
重要的三个概念
1、进程是一个静态的概念。
2、一个进程有一个主线程叫main()方法,是一个程序里面的,一个进程里面不同的执行路径。
3、在同一时间点,cpu只支持一个线程执行,因为cpu运行速度很多,我们看起来就像是多个线程同时执行一样。
二、线程的创建和启动
线程的创建
1、定义线程类实现Runnable
接口
- Runnable中只有一个方法:
public void run();用来定义线程运行体; - 使用Runnable接口可以为多个线程提供共享的数据;
- 在实现Runnable接口的类的run方法中可以使用Thread的静态方法;
- public static Thread currentThread()获取当前线程的引用。
//定义Runnable0类实现Runnable接口
public class Runnable0 implements Runnable {
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println("rRunnable0:"+i);
}
}
}
public class TestThread0 {
public static void main(String[] args) {
Runnable0 r0=new Runnable0();//new一个线程类对象
Thread t=new Thread(r0);//要启动一个新的线程必须new一个Thread对象出来,如果不启动一个新的线程而是直接调用——》r0.run();那就会先执行完run()方法,再执行主线程
t.start();//启动新线程,新线程执行的是run()方法,新线程与主线程会一起并行执行
for(int i=0;i<10;i++){
System.out.println("main:"+i);
}
}
}
2、定义一个Thread的子类并重写其run方法
定义一个Thread的子类并重写其run方法
class myThread extends Thread{
pubic void run(){…}
}
然后生成该类的对象
myThread myThreadd=new myThread(…)
//定义Runnable0类继承Thread对象
public class Runnable1 extends Thread {
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println("rRunnable0:"+i);
}
}
}
public class TestThread0 {
public static void main(String[] args) {
Runnable1 r1=new Runnable1();//new一个线程类对象
r1.start();//调用start()方法启动新开辟的线程
for(int i=0;i<10;i++){
System.out.println("main:"+i);
}
}
}
三、线程控制基本方法
1、isAlive()
判断线程是否还“活”着,就是线程是否还未终止
2、getPriority()
获得线程的优先级数值
3、setPriority()
设置线程的优先级数值
4、Thread.sleep()
将当前线程睡眠指定毫秒数
5、join()
调用某线程的该方法,将当前线程与该线程“合并”,也就是等待该线程结束,再恢复当前线程的运行。
6、yield()
让出CPU,当前线程进入就绪队列等待调度。
7、wait()
当前线程进入对象的wait pool。
8、notify()/notfyAll
唤醒对象的wait pool中的一个/所有等待线程。
- sleep()方法的使用
public class MyThread extends Thread{
boolean flag=true;//定义一个标记,用来控制循环的条件
public void run(){
while (flag){
System.out.println("======"+new Date().toLocaleString()+"=======");
try {
sleep(1000);
}catch (InterruptedException e) {
return;
}
}
}
}
public class TestThread2 {
public static void main(String[] args) {
MyThread myThread=new MyThread();
myThread.start();//调用start()方法启动新开辟的线程
try {
MyThread.sleep(10000);
System.out.println("主线程睡眠了10秒后再次启动了");
}catch (InterruptedException e){
e.printStackTrace();
}
myThread.flag=false;
}
}
运行结果:
- join()方法的使用
public class MyThread2 extends Thread {
MyThread2(String s){
super(s);
/*
* 使用关键字super调用父类的构造方法
* 父类Thread的其中的一个构造方法:public Thread (String name)
* 通过这样的构造方法可以给新开辟的线程命名,方便管理线程*/
}
public void run(){
for(int i=1;i<=5;i++){
System.out.println("我是\t"+getName());
try {
sleep(1000);
}catch (InterruptedException e){
return;
}
}
}
}
public class TestThread3 {
public static void main(String[] args) {
MyThread2 myThread2=new MyThread2("Mythread");
myThread2.start();//启动线程
try {
myThread2.join();//调用join()方法合并线程,将子线程Mythread合并到主线程里面,
// 线程合并后,程序的执行过程就相当于是方法的调用的执行过程
}catch (InterruptedException e){
e.printStackTrace();
}
for(int i=0;i<=5;i++){
System.out.println("我是 主线程 Thread");
}
}
}
运行结果
- yield()方法的使用
public class MyThread3 extends Thread {
MyThread3(String s){
super(s);
}
public void run(){
for(int i=1;i<=5;i++){
System.out.println(getName()+":"+i);
if(i%2==0){
yield();
}
}
}
}
public class TestThread4 {
public static void main(String[] args) {
MyThread3 m1=new MyThread3("m1");
MyThread3 m2=new MyThread3("m2");
/* 同时开辟了两条子线程m1和m2,m1和m2执行的都是run()方法 */
/* 这个程序的执行过程中总共有3个线程在并行执行,分别为子线程m1和m2以及主线程
*/
m1.start();//启动子线程m1
m2.start();//启动子线程m2
for(int i=0;i<=5;i++){
System.out.println("我是main Thread");
}
}
}
运行结果