java--多线程的概念与创建

来源:互联网 发布:为什么凌晨五点醒 知乎 编辑:程序博客网 时间:2024/06/05 00:14

进程:是一个正在执行中的程序。

每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。
线程:就是进程中的一个独立的控制单元。
线程在控制着进程的执行。

一个进程中至少有一个线程。
Java VM  启动的时候会有一个进程java.exe.
该进程中至少一个线程负责java程序的执行。
而且这个线程运行的代码存在于main方法中。
该线程称之为主线程。

扩展:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收机制的线程。


如何在自定义的代码中,自定义一个线程呢?
通过对api的查找,java已经提供了对线程这类事物的描述。就Thread类。
一、创建线程的第一种方式:继承Thread类。
步骤:
1,定义类继承Thread。
2,复写Thread类中的run方法。
目的:将自定义代码存储在run方法。让线程运行。
3,调用线程的start方法,

该方法两个作用:启动线程,调用run方法。

class  Test{public static void main(String[] args){Demo d1=new Demo();Demo d2=new Demo();Demo d3=new Demo("3333333");d1.start();d2.setName("222222");d2.start();d3.start();}}class Demo extends Thread{Demo(){}Demo(String name){super(name);}public void run(){System.out.println(this.currentThread()+"....."+this.getName()+"......"+this.toString()+"........");}}
结果是:

Thread[Thread-0,5,main].....Thread-0......Thread[Thread-0,5,main]........
Thread[3333333,5,main].....3333333......Thread[3333333,5,main]........
Thread[222222,5,main].....222222......Thread[222222,5,main]........


二、创建线程的第二种方式:实现Runable接口
步骤:
1,定义类实现Runnable接口
2,覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中。
3,通过Thread类建立线程对象。
4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
为什么要将Runnable接口的子类对象传递给Thread的构造函数。
因为,自定义的run方法所属的对象是Runnable接口的子类对象。
所以要让线程去指定指定对象的run方法。就必须明确该run方法所属对象。
5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

class  Test{public static void main(String[] args){Demo d=new Demo();Thread d1=new Thread(d);Thread d2=new Thread(d,"22222222");d1.start();d2.start();}}class Demo implements Runnable{public void run(){System.out.println(Thread.currentThread()+"....."+Thread.currentThread().getName()+"......"+Thread.currentThread().toString()+"........");}}
结果是:

Thread[Thread-0,5,main].....Thread-0......Thread[Thread-0,5,main]........
Thread[22222222,5,main].....22222222......Thread[22222222,5,main]........

实现方式和继承方式有什么区别呢?
实现方式好处:

避免了单继承的局限性。
在定义线程时,建立使用实现方式。
两种方式区别:
继承Thread:线程代码存放Thread子类run方法中。
实现Runnable,线程代码存在接口的子类的run方法。

线程状态类型

1. 新建状态(New):新创建了一个线程对象。
2. 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3. 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4. 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5. 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

线程基本控制方法:

sleep():使程序暂停一段时间。sleep()使当前线程进入阻塞状态,在指定时间内不会执行。注意该方法要捕捉异常。

yield():该方法与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会。

join():使调用该方法的线程在此之前执行完毕,也就是等待该方法的线程执行完毕后再往下继续执行。注意该方法也需要捕捉异常。如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测。

wait():使当前线程处于等待状态,直到另一个线程调用notify(),notifyAll()方法为止。

notify():唤醒在同步监听器上处于等待状态的单个线程,如果有多个线程在等待,则任意唤醒一个线程。

notifyAll():唤醒在同步监听器上处于等待状态的所有线程。

这三个方法都是java.lang.Object的方法。

interrupt() :中断线程。强制让线程恢复到运行状态中来。

currentThread():返回对当前正在执行的线程对象的引用。

isAlive() :测试线程是否处于活动状态

toString() :返回该线程的字符串表示形式,包括线程名称、优先级和线程组。
线程组:谁开启的线程,这个线程就属于谁的组。ThreadGroup类中可查阅

join():当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。

setDaemon():将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。该方法必须在启动线程前调用。 


开发中多线程常用的方式:

class ThreadTest {public static void main(String[] args) {//1111111111111111111111new Thread(){public void run(){for(int x=0; x<100; x++){System.out.println(Thread.currentThread().getName()+"....."+x);}}}.start();//2222222222222222222222for(int x=0; x<100; x++){System.out.println(Thread.currentThread().getName()+"....."+x);}//33333333333333333333333Runnable r  = new Runnable(){public void run(){for(int x=0; x<100; x++){System.out.println(Thread.currentThread().getName()+"....."+x);}}};new Thread(r).start();//44444444444444444444444new Test1().start();}}class Test1 extends Thread{public void run(){for(int x=0; x<100; x++){System.out.println(Thread.currentThread().getName()+"....."+x);}}}


0 0
原创粉丝点击