总结:1. 使用三种方式创建线程和启动线程
2. 三种方式的优缺点:
继承thread的优缺点: 优点:代码更简单,使用getName就可以直接得到线程的名称
缺点:不能共享成员feild(不符合面向对象的思想)
实现 Runnnable的优缺点:代码复杂了点,但是各个线程共享一份变量。
实现Callable的优缺点:可以有返回值,还可以抛异常哦!(这个接口是在util的这个包中)
3. 关于线程生命周期的五种状态: 新建(就是刚刚new出来的时候) 就绪(就是调用start的时候) 运行 堵塞,死亡
注意: * 调用了start 的方法,仅仅是就绪的状态,看下面的例子。!!!!!!!!
* 线程死亡之后,并不能重新启动。可用isLive测试。在新建和死亡的状态,isLive为 false。即是在它启动死亡之后,再次启动来测试。看会不会报错。
4 . 控制线程的常见的方法:
* join就是将线程加入到另一个线程中去,这样会造成不是并发的执行。
* t.setDaemon(true)表示将该线程申明为后台线程,当前台线程执行完死亡后,后台的线程也不执行了。
* sleep方法表示当前的线程睡一会儿,cpu爱执行谁执行谁
* yield移植性不好,不建议使用。表示礼让给别人执行,但是别人优先级比自己低的话,还是会执行自己。
sleep与yield的区别;
* sleep礼让很干脆,但是yield是一个伪君子,还要看别人的优先级。
* sleep之后,仅仅处于堵塞的状态,而yield处于就绪的状态。
* sleep抛异常,yield不抛异常
* sleep的移植性更好,建议使用。
5. 线程优先级的问题:默认的情况下都是5,但是主线程改变优先级之后,其他的与他保持一致。除非其它的线程重新设置优先级。
max 10 norm5 min1
代码参考:
package com.huxin.thread.test;
/*
* 这个程序告诉我们: 采用继承的方式创建一个线程的时候,不能共享线程类的实例变量。
*/
public class FirstThread extends Thread {
private int i;
public void run(){
for(;i<10;i++){ //这一种循环,还是第一次见呢
System.out.println(getName()+" "+i);
}
}
public static void main(String[] args) {
for(int i=0;i<10;i++){
System.out.println(FirstThread.currentThread().getName()+i);
if(i==5){
new FirstThread().start();
new FirstThread().start();
}
}
}
}
/*
* 实现这个街口,它是共享这个变量的哦!!!!!
*/
public class SecondThread implements Runnable{
private int i;
public static void main(String[] args) {
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
if(i==20){
SecondThread st = new SecondThread();
new Thread(st,"新的线程一").start();
new Thread(st,"新的线程二").start();
}
}
}
public void run() {
for(;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class ThirdThread implements Callable<Integer>{
private int i ;
public static void main(String[] args) {
ThirdThread tt = new ThirdThread();
FutureTask ft = new FutureTask(tt);
new Thread(ft,"有返回值的线程").start();
try {
System.out.println(ft.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("怎么还没有到我执行啊?");
}
//亲,看这里,可以有返回值,可以抛异常哦
public Integer call() throws Exception {
for(;i<10;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
return 3;
}
}
package com.huxin.thread.test;
/*
* 验证一个容易犯错误的问题;
* main 20
main 21
main 22
main 23
main 24
Thread-0 0
Thread-0 1
main 25
调用start的方法的时候,线程仅仅处于就绪的状态,而并非运行的状态
*/
public class LivingTest extends Thread{
private int i;
public static void main(String[] args) {
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
if(i==20){
new LivingTest().start();
}
}
}
public void run(){
for(;i<100;i++){
System.out.println(getName()+" "+i);
}
}
/*
* 线程死亡之后,不能再次启动,并且线程在新建,死亡之后,调用isAlive()的方法,返回为false
*/
public class LivingTest2 extends Thread {
private int i;
public static void main(String[] args) {
LivingTest2 test2 = new LivingTest2();
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
if(i==20){
test2.start();
System.out.println(test2.isAlive()); //运行结束以后,线程就死亡
}
}
if(!test2.isAlive()){
test2.start(); //Exception in thread "main" java.lang.IllegalThreadStateException
}
}
public void run(){
for(;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}