java 每秒调用一次 java 每秒循环一次_并发编程

  • 线程就是内存中的一个对象,线程并不是调用start方法之后就立刻开始执行而是表示准备好了(Cpu可能正在执行其他线程),应该进行排队。当Cpu有时间片了,就分配给这个线程开始执行,如果到时间了,那么停止运行,重新排队。重复这个过程,直至运行完毕。
  • 如果运行中出现状况,那么会停止运行,进入阻塞状态,直至解除才能进入就绪状态,准备排队。如果没有解除那么就会中止。
  • 简言之就是 创建(new Thread) 就绪(start()) 执行(run()) ( 阻塞 解除阻塞 ) 就绪
  • 执行反复循环直至执行完毕 挂起包括就绪和阻塞状态
  • java 每秒调用一次 java 每秒循环一次_并发编程_02

  • 当线程试图获得一个对象的锁,而该锁被其他线程持有,那么当前线程进入阻塞状态
    当调用wait或join方法时,会进入等待状态
    当一个线程被阻塞或终止时,另一个线程被设置为运行状态。当一个线程重新激活时,线程调度器会检查它是否具有比当前运行线程更高的优先级,如果是这样,那么线程调度器会从当前运行线程中挑选一个,剥夺其运行权,选择一个新的线程继续运行
  • java 每秒调用一次 java 每秒循环一次_高并发_03

  • 这些方法是Thread类的静态和动态方法,如果想调用静态方法 Thread.方法名
  • 如果想调用动态方法,那么这个线程只能是用第二种方法创建的(extends Thread),否则无法使用Thread类的方法
  • isAlive活着的定义是就绪、执行、阻塞状态
  • 死了的定义是还没开始、执行完毕
  • 线程是有优先级的,优先级高的获得Cpu执行时间长,并不代表优先级低的就得不到执行
  • java 每秒调用一次 java 每秒循环一次_并发编程_04

  • sleep是暂停一会,是静态方法,不需new 出Thread对象就可以执行
  • java 每秒调用一次 java 每秒循环一次_java_05

  • 这个异常是睡眠时 被打断的异常,所以必须写try catch
  • 并且sleep方法执行过程中获得当前对象的锁,其他线程无法访问当前资源
  • Thread的sleep方法在哪个线程执行哪个线程就会睡眠
  • sleep方法适用于几个场合:
    1.倒计时,间隔n秒打印一个数字
    2.模拟网络延时
    ————————————————————————
  • java 每秒调用一次 java 每秒循环一次_java_06

  • 方法interrupt可以主动的中断线程,打断之后会抛异常InterruptedException
  • 调用Interrupt方法时,线程的中断状态将被置位。这是每一个先后才能都具有的boolean标志
  • 每个线程都应该不时检查这个标志,以判断线程是否被中断
    如果得到中断状态得到置位?
    调用静态的Thread.currentThread.isInterrupted()方法,但是线程处于阻塞状态时无法检测是否中断
    当在一个被阻塞的线程(wait sleep)调用interrupt方法,阻塞调用被会InterruptedException异常中断。
    一个被中断的线程未必会终止,如何相应中断应该取决于线程是否重要,是否应该不理会异常
    如果在每次循环之后都调用sleep或其他的可中断的方法,那么isInterrupted方法是无效的。
    如果在中断之后,中断状态被置位,然后调用sleep方法,此时不会睡眠,而是清除中断状态,并抛出中断异常。因此循环调用sleep是没有必要调用isInterrupted方法来判断是否被中断(sleep方法本身会进行判断,如果中断那么抛异常)
    interrupted和isInterrupted是两个方法
  • 前者是一个静态方法,检测是否被中断,并且清除中断状态;后者是一个非静态方法,只会进行检测。
  • 如果在某个方法中调用了sleep方法,应该将InterruptedException异常抛出
  • 应该在最终的run方法中来将InterruptedException异常捕捉
    这种方法可以使子线程结束,但这种方法不好,太粗暴
  • stop方法更加粗暴,不要使用

线程停止方法:

java 每秒调用一次 java 每秒循环一次_并发编程_07


如何让线程自然停止?

run方法结束,线程就结束,可以在run方法中加一个flag和一个可以设置flag为false的关闭方法,当主线程结束想要分支的线程也随之结束的话,可以调用shutDown 方法使run中的循环结束。run方法结束,该分支线程结束。

但是对于阻塞方法的调用,这种停止是无效的

示例1(不温和的停止):

import java.util.*;
public class test {
	public static void main(String []args){
		MyThread mt = new MyThread();
		mt.start();//方法2:start而不是run来启动进程
		try{
			Thread.sleep(10000);
		}catch (InterruptedException e){}
		mt.interrupt();
	}
}

class MyThread extends Thread {
	public void run (){
		while(true ){
			System.out.println("=="+ new Date() + "=="); //该循环每秒执行一次
			try{
				sleep(1000);
			}catch (InterruptedException e ){
				return ;
			}
		}
	}
}

输出结果:
Fri Mar 04 19:38:59 CST 2016
Fri Mar 04 19:39:00 CST 2016
Fri Mar 04 19:39:01 CST 2016

示例2(温和的停止):

public class test {
	 public static void main(String []args){
		 MyThread thread = new MyThread();
		 Thread t = new Thread(thread);
		 t.start();
		 for(int i = 0; i<1000 ;i++){
			 if(i %100 == 0 && i != 0)
				 System.out.println("The main thread:"+ i);
		 }
		 System.out.println("The main thread is over");
		 thread.shutDown(); //代表这主线程执行完毕,程序最后将分支结束
	 }
 }
class MyThread implements Runnable {
	 boolean flag = true;//可以调用shutdown方法使这个死循环停止
	 public void run() {
		 int i = 0;
		 while(flag){
			 System.out.println(i++);
		 }
	 }
	 public void shutDown () {
		 flag = false;
	 }
 }

————————————————————————
join 方法:用于合并某个线程

  • start线程之后可以join这个线程
  • join方法的作用是将分出来的线程合并回去,等待分出来的线程执行完 毕后继续执行原有线程。类似于方法调用。
  • join方法也会抛出InterruptedException
    Thread类的构造方法1:
    Thread类的构造方法2:
  • new 一个子类对象的同时也new了其父类的对象,只是如果不显式调用父类的构造方法super(),那么会自动调用无参数的父类的构造方法。
    可以在自定义类MyThread中(继承自Thread类)中写一个构造方法,显式调用父类的构造方法,其参数为一个字符串,表示创建一个以该字符串为名字的Thread对象。效果是创建了一个MyThread对象,并且其父类Thread对象的名字是给定的字符串。
  • 如果不显式调用父类的构造方法super(参数),那么默认父类Thread是没有名字的。
  • Thread类有一个动态方法可以返回线程的名称 getName。
    在子类对象中调用这个方法,且其父类对象是有名字的,那么返回的是父类Thread的名字
    示例:
public class test {
	public static void main(String []args){
		MyThread thread = new MyThread("mimi");
		thread.start();
		try{
			thread.join();
		}catch (InterruptedException e ){}
		for(int i = 0; i<= 5;i++) {
			System.out.println("I am Main Thread");
		}
	}
}
class MyThread extends Thread {
	MyThread (String name){
		super(name);
	}
	public void  run (){
		for(int i = 0; i<=5 ;i++){
			System.out.println("I am "+ getName());
			try{
				sleep(1000);				
			}catch (InterruptedException e){
				return ;
			}
		}
	}
}
输出结果:
I am mimi
I am mimi
I am mimi
I am mimi
I am mimi
I am mimi
I am Main Thread
I am Main Thread
I am Main Thread
I am Main Thread
I am Main Thread
I am Main Thread

————————————————————————
yield 方法:让出Cpu,让一次时间片
示例:

public class test {
	public static void main(String []args){
		MyThread m1 = new MyThread("mimi");
		MyThread m2 = new MyThread("lala");
		m1.start();
		m2.start();//共有三条分支,三个线程
	}
}

class MyThread extends Thread {
	MyThread(String name){
		super(name);
	}
	public void run(){
		for(int i = 0; i< 100 ;i++){
			System.out.println(getName()+":"+i);
			if(i %10 == 0){
				yield();
			}
		}
	}
}
部分输出结果:
mimi:8
lala:9
mimi:9
lala:10
mimi:10
lala:11
mimi:11
lala:12
mimi:12

当一个线程达到10时无论是刚开始还是执行一段时间都会切换到其他线程继续执行