在Java中创建线程有两种方法:使用Thread类和使用Runnable接口。在使用Runnable接口时需要建立一个Thread实例。因此,无论
是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例
主线程也有可能在子线程结束之前结束。并且子线程不受影响,不会因为主线程的结束而结束。
在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实
际上都会启动一个JVM,每一个jVM实习在就是在操作系统中启动了一个进程。
main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。
实现Runnable接口比继承Thread类所具有的优势:
如卖票系统,票数count,实现runnable方式启动多个线程,多个线程处理同一个count(一个线程减一后其他线程处理的是减一后
的数据);thread方式启动过个线程,每个线程都有一个count,互不影响(某个线程减一后,其他线程处理的不是该线程减一后的
数据,而是其他线程中自己的数据)
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
所谓同步就是在统一时间段中只有有一个线程运行,其他的线程必须等到这个线程结束之后才能继续执行。
采用同步的话,可以使用同步代码块和同步方法两种来完成。
【同步代码块】:
语法格式:
synchronized(同步对象){
//需要同步的代码
}
但是一般都把当前对象this作为同步对象。
【同步方法】
也可以采用同步方法。
语法格式为synchronized 方法返回类型方法名(参数列表){
// 其他代码
}
3、线程合并——join
线程的合并的含义就是将几个并行线程的线程合并为一个单线程执行,应用场景是当一个线程必须等待另一个线程执行完毕才能执行时,Thread类提供了join方法来完成这个功能,注意,它不是静态方法。
从上面的方法的列表可以看到,它有3个重载的方法:
void join()
当前线程等该加入该线程后面,等待该线程终止。
void join(long millis)
当前线程等待该线程终止的时间最长为 millis 毫秒。 如果在millis时间内,该线程没有执行完,那么当前线程进入就绪状态,重新等待cpu调度
void join(long millis,int nanos)
等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。如果在millis时间内,该线程没有执行完,那么当前线程进入就绪状态,重新等待cpu调度
sleep是静态方法,是谁掉的谁去睡觉,就算是在main线程里调用了线程b的sleep方法,实际上还是main去睡觉,想让线程b去睡觉要在b的代码中掉sleep
- public class Test1 {
- public static void main(String[] args) throws InterruptedException {
- System.out.println(Thread.currentThread().getName());
- MyThread myThread=new MyThread();
- myThread.start();
- myThread.sleep(1000);//这里sleep的就是main线程,而非myThread线程
- Thread.sleep(10);
- for(int i=0;i<100;i++){
- System.out.println("main"+i);
- }
- }
- }