线程创建方式

来源:互联网 发布:记简谱的软件 编辑:程序博客网 时间:2024/05/22 08:26
  1. 创建线程的3种方式:
    1)继承Thread类
    ①自定义线程类继承Thread,重写 run() 方法,把线程要做的任务写在run()方法中。
    ②创建自定义线程对象,调用 start()方法启动线程。
//1,自定义线程类继承Thread,重写 run() 方法,把线程要做的任务写在run()方法中  Thread mt = new Thread(){    public void run() {        System.out.println("线程要做的代码任务");    }};//2,创建自定义线程对象,调用 start()方法启动线程mt.start();

2)实现Runnable接口
①自定义Runnable接口的实现类,并实现 run() 方法,把线程要做的任务写在run()方法中。
②创建Thread对象,构造函数中传入Runnable接口的实现类对象。
③调用start()方法启动线程,运行时jvm内部会自动调用Runnable实现类的run()方法。

//1,自定义Runnable接口的实现类,并实现 run() 方法,把线程要做的任务写在run()方法中Runnable myRunnable = new Runnable(){    public void run() {            System.out.println("线程要做的代码任务");    }};//2,创建Thread对象,构造函数中传入Runnable接口的实现类对象Thread t = new Thread(myRunnable);//3,调用start()方法启动线程,运行时jvm内部会自动调用Runnable实现类的run()方法t.start();

3)实现Callable接口
①创建Callable接口的实现类,并实现call()方法,把线程要做的任务写在call()方法中,该方法有返回值。
②创建FutureTask对象,构造函数中传入Callable接口的实现类对象【FutureTask中封装了Callable对象的call()方法的返回值】
③创建Thread对象,构造函数中传入FutureTask对象。【FutureTask是Runnable接口的实现类】
④调用start()方法启动线程
⑤调用FutureTask对象的get()方法来获得线程执行结束后的返回值

//1,创建Callable接口的实现类,并实现call()方法,把线程要做的任务写在call()方法中,该方法有返回值Callable<Integer> myCallable = new Callable<Integer>(){        public Integer call() throws Exception {                int sum = 0;                for(int i = 0; i <= 100; i++){                        sum += i ;                }                return sum;        }};//2,创建FutureTask对象,构造函数中传入Callable接口的实现类对象FutureTask<Integer> future = new FutureTask<Integer>(myCallable);//3,创建Thread对象,构造函数中传入FutureTask对象。【FutureTask是Runnable接口的实现类】Thread t = new Thread(future);//4,调用start()方法启动线程t.start();//5,调用FutureTask对象的get()方法来获得线程执行结束后的返回值System.out.println(future.get());           //5050

三种方式的对比:
1)实现Runnable、Callable接口的方式
优势是:①自定义线程类只实现了Runnable接口或Callable接口,还可以继承其他类。
②多个相同线程来共享同一份任务数据时,如多个窗口售票。使用该方式对线程对象和线程任务进行解耦,较好地体现了面向对象的思想。
劣势是:①不能直接使用Thread中的方法,需要先通过Thread.currentThread()获取到线程对象后,才能使用Thread的方法,代码复杂。
2)使用继承Thread类的方式
优势是:①编写简单,可以直接使用Thread类中的方法。
劣势是:①因为Java中的单继承机制,线程类已经继承了Thread类,所以不能再继承其他类。

2.Runnable接口和Callable接口的区别
1)实现Callable接口的线程,需实现call()方法,该方法有返回值,能返回线程执行结果;
而实现Runnable接口的线程需实现run()方法,该方法无返回值,不能返回线程执行结果;
2)Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;

匿名类创建线程

方式①new Thread(){                                       public void run(){                                  System.out.println("线程要执行的任务代码");    }}.start();                                      方式②new Thread(new Runnable(){                          public void run() {                                 System.out.println("线程要执行的任务代码");    }}).start(); 

3.wait方法和sleep方法的区别
sleep()方法:
1)该方法是Thread类中的静态方法:使当前执行的线程睡眠(暂停执行)指定的时间
2)sleep()期间不会释放对象锁,如果在同步代码块中,其他线程不能访问共享资源。
wait()方法:
1)该方法是Object类中的方法:使当前线程挂起,当对象调用notify()或者notifyAll()或者时间到期,则从wait()中恢复执行。
2)用在同步代码块中,wait()期间会释放对象锁
一般而言,wait()用于线程间的通信,sleep()用于线程状态的控制

4.什么是线程安全
线程安全:多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。
线程不安全:不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。

原创粉丝点击