java线程的基础实例解析

网友投稿 247 2023-03-03


java线程的基础实例解析

java中建立线程可以有两种方式,分别是继承Thread类和实现Runnable接口。

继承Thread

public class MyThread extends Thread{

public MyThread(String name){

super(name);

}

int i;

public void run(){

for(i=0;i<5;i++){

System.out.println(getName()+"--"+i);

}

}

public static void main(String[] agrs){

new MyThread("线程1").start();

new MyThread("线程2").start();

}

}

/*

线程1--0

线程1--1

线程1--2

线程1--3

线程1--4

线程2--0

线程2--1

线程2--2

线程2--3

线程2--4

*/

如上,java中的线程对象必须一个类的形式创建,而该类中必须重写基类的run()方法,该方法其实就是线程的执行体。调用该类实例的start方法则就隐式的调用了run方法。

不难看出,由于new了2次MyThread,所以两次的实例是不同的,即各自都有各自的i变量,相互独立。

Runnable接口

public class MyRunnable implements Runnable{

int i;

public void run(){

for(i=0;i<50;i++){

System.out.println(Thread.currentThread().getName()+"--"+i);//不能直接this.getName()

}

}

public static void main(String[] agrs){

MyRunnable myRun=new MyRunnable();

new Thread(myRun,"线程1").start();

new Thread(myRun,"线程2").start();

}

}

/*

线程1--0

线程1--1

线程2--0

线程2--3

线程2--4

线程2--5

线程2--6

线程2--7

线程2--8

线程2--9

线程2--10

线程2--11

线程2--12

线程2--13

线程2--14

线程2--15

线程1--2

线程2--16

线程2--18

线程2--19

线程2--20

线程2--21

线程2--22

线程2--23

线程2--24

线程1--17

线程2--25

线程1--26

线程2--27

线程1--28

线程1--30

线程2--29

线程1--31

线程2--32

线程2--34

线程2--35

线程2--36

线程2--37

线程1--33

线程2--38

线程1--39

线程1--41

线程2--40

线程1--42

线程1--44

线程1--45

线程2--43

线程1--46

线程2--47

线程2--49

线程1--48

*/

可以看出,由于实现这种方式是将某一个对象做为target加载到Thread类上,所以即使newhttp://再多的Thread对象,只要target是同一引用的对象,则就调用该对象的run方法,所有线程均共享该target对象的资源,所以会看到线程1和线程2一共输出了51次,2条线程共同完成了i从0到49的输出,而并不像上面那样分别输出5次。至于为什么输出了51条,两条线程几乎在同一时刻进入就绪状态(start方法只是让线程进入就绪状态),观察上面的i变量不难发现当i等于0时,此时线程1和线程2均同时处于运行状态,产生了并发现象,共同输出了i=0,而此之后CPU通过不断的切换线程,使得在同一时刻只有一条线程在输出。

线程状态

线程分为4个状态

就绪状态:调用start方法则进入就绪状态。

运行状态:处于就绪状态的线程会被jvm进行调度从而成为运行状态。

阻塞状态:如有某些同步方法未返回结果则出现阻塞状态,或sleep和yeild。

死亡状态:方法体执行完毕或者强行stop某个线程。

线程的基本操作

join()合并线程:当前线程调用某线程的join方法后将会等待某线程执行完毕后本线程才会继续。

sleep(long milliseconds)线程睡眠:阻塞当前线程,只有阻塞的时间到了才会继续下去。再阻塞的同时,会将CPU占有权交给其他线程,所以常常利用sleep(1)来切换线程。

**yield()线程让步:**yeild类似与sleep,但是它只会让步于比自己级别高或者同级别的其他线程,若没有其他线程均比自己级别低则再次执行本线程。

后台线程

一个程序被操作系统执行后将有一个进程,一个进程至少有一个线程(主线程),主线程并没有比其他线程有太多的特殊之处,只因为它是最早被执行的线程,在主线程中将会创建其他线程,若不指明则默认创建的是前台线程(包括main线程),若调用setDaemon(true)则显式的将该线程设置为后台线程,后台线程为Daemon线程,从名字就能看出,它的主要作用是为其他线程提供守护,服务的功能。当所有前台线程结束后,后台线程将会被强制结束,因为它此时已经没有存在的意义了。

前台线程

public class ForeAndBackThread extends Thread{

public ForeAndBackThread(String name){

super(name);

}

public void run(){

int i;

for(i=0;i<9999;i++){

System.out.println(this.getName()+"--"+i);

}

}

public static void main(String[] args){

ForepEgUUhkHdnAndBackThread th=new ForeAndBackThread("线程A");

//th.setDaemon(true);

th.start();

int j;

for(j=0;j<3;j++){

System.out.println(Thread.currentThread().getName()+"--"+j);

}

}

}

程序完整的输出子线程中0到9998;说明主线程并没有什么特殊的,它的结束并不会影响其他前台线程的运行。

后台线程

public class ForeAndBackThread extends Thread{

public ForeAndBackThread(String name){

super(name); pEgUUhkHdn

}

public void run(){

int i;

for(i=0;i<9999;i++){

System.out.println(this.getName()+"--"+i);

}

}

public static void main(String[] args){

ForeAndBackThread th=new ForeAndBackThread("线程A");

th.setDaemon(true);

th.start();

int j;

for(j=0;j<3;j++){

System.out.println(Thread.currentThread().getName()+"--"+j);

}

}

}

程序并不能完整的输出0-9998就退出了,说明前台主线程结束后,jvm强制结束了后台线程。

总结

以上就是本文关于java线程的基础实例解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:浅谈Spring单例Bean与单例模式的区别
下一篇:浅谈自定义注解在Spring中的应用
相关文章

 发表评论

暂时没有评论,来抢沙发吧~