<线程的创建与启动</span></h1><p></p><p>总结下有三种方式:<常用的就是前面两种第一种 创建Thread类的子类对象</span></h2><p>1定义Thread类的子类</p><p>2重写run()方法</p><p>3创建Thread的子类实例,创建线程对象</p><p>4调用start()的start()方法来启动该线程</p><pre name="code" class="java">public class ThreadOne extends Thread //第一步 定义一个类继承Thread
{
private int a;//定义一个成员变量
//重写run()方法
public void run(){
for(;a<249;a++)
{
System.out.println(getName()+""+a);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
for(int a=0;a<249;a++)
{
System.out.println(Thread.currentThread().getName()+"--"+a);
if( a==10)
{
//创建线程
ThreadOne TO=new ThreadOne();
//启动该线程
TO.start();
ThreadOne TW=new ThreadOne();
TW.start();
ThreadOne TH=new ThreadOne();
TH.start();
//还是可以采用链式编程
new ThreadOne().start();
new ThreadOne().start();
}
}
}
}
第二种 实现Runnable接口创建线程类
1定义Runnable接口地实现类
2重写该接口的run()的方法
3创建该Runnable()接口实现类的实例
4启动start()方法
注意:API中
Thread(Runnable target) 分配新的 Thread 对象。 |
Thread(Runnable target,String name) |
有这两个方法
//定义一个类实现Runnable接口
public class RunnableTwo implements Runnable {
private int a;
//重写run()方法
public void run(){
for(;a<249;a++)
{
//注意,这里跟第一个程序不同?实现Runnable接口的类必须要注意实现currentThread()方法
System.out.println(Thread.currentThread().getName()+"--"+a);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
for(int a=0;a<259;a++)
{
System.out.print(Thread.currentThread().getName()+"—-"+a);
if(a==10)
{
//Runnable类实现实例化
RunnableTwo RT=new RunnableTwo();
//通过构造器实现线程
Thread one=new Thread(RT,"1");
Thread two=new Thread(RT,"2");
//启动线程
one.start();
two.start();
}
}
}
}
我们一般喜欢采用第二个方法;
当然查阅API在Java5中还新增了一种方法;接下来来讲下该方法
第三种Callable
看API是怎么介绍的
java.util.concurrent
接口 Callable<V>
-
类型参数:
-
V
- call 方法的结果类型
-
所有已知子接口:
- JavaCompiler.CompilationTask
public interface Callable<V>
返回结果并且可能抛出异常的任务。实现者定义了一个不带任何参数的叫做 call 的方法。
Callable 接口类似于 Runnable
,两者都是为那些其实例可能被另一个线程执行的类设计的。但是Runnable 不会返回结果,并且无法抛出经过检查的异常。
Executors
类包含一些从其他普通形式转换成Callable 类的实用方法。
-
从以下版本开始:
- 1.5 另请参见:
-
Executor
方法摘要 | |
---|---|
V | call() 计算结果,如果无法计算结果,则抛出一个异常。 |
第一我们可以读出有返回值
第二读不出来的就就抛出异常但是这里就很难受了,知道了这些并不能调用,返回值作为targer太扯淡了,我继续查了下API
接口 Future<V>
-
类型参数:
-
V
- 此 Future 的 get 方法所返回的结果类型
boolean | cancel(boolean mayInterruptIfRunning) 试图取消对此任务的执行。 |
V | get() 如有必要,等待计算完成,然后获取其结果。 |
V | get(long timeout,TimeUnit unit) 如有必要,最多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)。 |
boolean | isCancelled() 如果在任务正常完成前将其取消,则返回true。 |
boolean | isDone() 如果任务已完成,则返回true。 |
这又是一个接口,再看看有没有现成的类
类 FutureTask<V>
FutureTask(Callable<V> callable) 创建一个FutureTask,一旦运行就执行给定的 Callable。 |
FutureTask(Runnable runnable,V result) 创建一个FutureTask,一旦运行就执行给定的 Runnable,并安排成功完成时 get 返回给定的结果 。 |
哈哈,终于找到我们想要的东西,不BB,直接上代码。
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class ThreeCallable implements Callable<Integer> {
private int a;
private int b;
//重写call()方法
public Integer call() throws Exception{
for(int a=0;a<249;a++)
{
System.out.println(Thread.currentThread().getName()+"--"+a);
while(a==100){
b=a;
break;
}
}
return b;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建该对象实例化
ThreeCallable TC=new ThreeCallable();
//FutureTask是一个类,类里传入TC这个实例,来得到放回值类型
FutureTask<Integer> target=new FutureTask<Integer>(TC);
for(int a=0;a<249;a++)
{
System.out.println(Thread.currentThread().getName()+"--"+a);
if(a==10)
{
new Thread(target,"1").start();
}
}
try
{
// 得到放回值
System.out.println("线程返回值"+target.get());
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
现在来总结下:
想要取得Callable返回值的方法,不想要返回值的话就跟第二种一样了
1 定义一个类实现Callable接口;
2 重写run方法
3创建这个类的实例
4使用FutureTask类来包装Thread类的对象。
5上步骤中的对象来作为Thread的target对象创建,接着启动线程
6通过get()方法来得到返回值类型。
总结:三种方式的优缺点
1后面2种方式明显可以体现出多态,不仅能实现Runnable、Callable接口,还可以实现其他接口
2后面两种多个线程可以共享一个target。
3前面编写比较简单,后面两种方式就比较多。
线程的周期
新建到就绪:通过start()方法调用后即可。
就绪到运行:需要配置CPU资源。
运行到阻塞:1 sleep()方法。
2 IO阻塞
3 等待同步锁
4 suspend()把程序挂起,这可能会导致死锁。
5 等待通知wait()。
阻塞到就绪:1 sleep()时间到了
2 IO方法放回
3 获得同步锁
4 等待收到通知notify()。唤醒线程。nofityAll(),唤醒所有线程。
5 resume()重写开始
运行到阻塞: 1 yield()线程让步
2 失去CPU资源
就绪到死亡: 1 stop()停止
2 Error()或者Exception
3 run()/call()方法执行完成
控制线程
void | join() 等待该线程终止。 |
void | join(long millis) 等待该线程终止的时间最长为 millis 毫秒。 |
void | join(long millis, int nanos) 等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。 |
void | setDaemon(boolean on) 将该线程标记为守护线程或用户线程。 |
static void | sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。 |
static void | sleep(long millis, int nanos) 在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。 |
static void | yield() 暂停当前正在执行的线程对象,并执行其他线程。 |
void | setPriority(int newPriority) 更改线程的优先级。 |
