A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 陈欢 中级黑马   /  2012-7-17 21:04  /  2661 人查看  /  13 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 陈欢 于 2012-7-20 00:39 编辑

关于java中多线程的几种方法
1.java线程中可以实现Runnable借口或者继承Thread类实现,实际中应该怎么样使用呢,还是没怎么理解?(哪位高人有没有详细代码解释一下呢)

13 个回复

倒序浏览
建议:把代码弄到代码块上!

你的意思是怎么在main中读取bk1中的private变量吧;
很抱歉不可以!其实非要那么做就用暴力反射,我想那也不是你的意愿!
为什么不可以呢?序列号可以说是为了让对象长久存储!多用在游戏编程,流行的云计算等技术基础!
序列化不会破坏java的规则!所以以前在main中不可以访问private变量;现在也不可以!
那么Book bk1=(Book)oi.readObject();就好比book bk1=new book();
利用bk1能做的和以前一样!
序列化的目的是是为了本地化存储对象,可能现在demo中不是太能体现价值。



回复 使用道具 举报
为什么在另一个帖中出现了我的上一个贴的答案呢?求解释?

关于这个贴中的问题:到底是继承Thread还是runnable接口?
看实际情况:但通常会实现runnable接口.因为这样你还可以另外继承一个类,
毕竟一个类只能继承一个类,如果继承了thread,就会不能继承其他的了;
而且很多人也是这么做的。
回复 使用道具 举报
陈欢 来自手机 中级黑马 2012-7-17 21:54:04
板凳
可能有点小巧合吧,我要是明白就去回帖了
回复 使用道具 举报
其实很简单  c++中一个子类可以继承多个父类  但是java中只能继承一个父类,也就是说名额有限,你要是用来继承了Thread类了  就不能继承其他的类了,在实际开发中往往都要继承其他的类的,所以就用事先runnable接口了
回复 使用道具 举报
陈欢 来自手机 中级黑马 2012-7-17 22:00:52
地板
哦,看过你们的解释,我基本上明白了,多谢
回复 使用道具 举报
陈欢 来自手机 中级黑马 2012-7-17 22:02:17
7#
哦,看过你们的解释我基本上都明白了,多谢
回复 使用道具 举报
徐帅 中级黑马 2012-7-17 22:08:24
8#
本帖最后由 徐帅 于 2012-7-17 22:09 编辑

其实第一种方法具有局限性,所以大多数使用第二种方式,关于两种方式,总结如下:
创建线程的第一种方式:继承Thread类。
  步骤:
  1> 定义类继承Thread。
  2> 复写Thread类中的run方法。
    目的:将自定义代码存储在run方法。让线程运行。
  3> 调用线程的start方法,
    该方法两个作用:启动线程,调用run方法。

第二种方式:实现Runnable接口
   由来:如果自定义的类中有多线程要运行的代码。但是该类有自己的父类。
    那么就不可以再继承Thread,因为java中不支持多继承。
  步骤:
   1>定义类实现Runnable接口
   2>覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中。
   3>通过Thread类建立线程对象。
   4>Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。   
  5>调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

2  实现方式和继承方式的区别
   1>实现方式好处:避免了单继承的局限性。
     在定义线程时,建立使用实现方式。
  2> 继承Thread:线程代码存放Thread子类run方法中。
     实现Runnable,线程代码存在接口的子类的run方法。







评分

参与人数 1技术分 +1 收起 理由
刘笑 + 1 虽然答非所问,但总结的比较好.

查看全部评分

回复 使用道具 举报
陈欢 中级黑马 2012-7-17 22:15:46
9#
徐帅 发表于 2012-7-17 22:08
其实第一种方法具有局限性,所以大多数使用第二种方式,关于两种方式,总结如下:
创建线程的第一种方式: ...

你写的太清楚,这样理解的更深刻了,厉害,多谢
回复 使用道具 举报
陈欢 发表于 2012-7-17 22:15
你写的太清楚,这样理解的更深刻了,厉害,多谢

呵呵,都是从视频上总结出来的,一起加油
回复 使用道具 举报
还是举老师的例子:假设有10张票,需要两个窗口卖(即两个线程),继承Thread类的写法如下:
  1. public class ThreadDemo {
  2. public static void main(String[] args) {
  3. Ticket1 t1=new Ticket1();
  4. Ticket1 t2=new Ticket1();
  5. t1.start();
  6. t2.start();
  7. }
  8. }
  9. class Ticket1 extends Thread{
  10. private int ticket=10;
  11. public void run(){
  12. while(true){
  13. if(ticket>0){
  14. System.out.println("继承Thread类:"+Thread.currentThread().getName()+"---sales:"+ticket--);
  15. }
  16. }
  17. }
  18. }
复制代码
实现Runnable接口的方式如下:
  1. public class ThreadDemo {
  2. public static void main(String[] args) {
  3. Ticket2 t=new Ticket2();
  4. new Thread(t).start();
  5. new Thread(t).start();
  6. }
  7. }
  8. class Ticket2 implements Runnable{
  9. private int ticket=10;
  10. public void run(){
  11. while(true){
  12. if(ticket>0){
  13. System.out.println("实现Runnable接口:"+Thread.currentThread().getName()+"---sales:"+ticket--);
  14. }
  15. }
  16. }
  17. }
复制代码
他们运行打印结果分别为:
从打印结果可以看到:如果是多线程当继承Thread时,每个窗口都会卖掉10张票,造成卖票系统出错
而实现Runnable,就达成了数据的共享,不管有多少个窗口,卖完10张票就没有了,所以为了多线程的安全性最好实现Runnable接口
第二个原因就是,类可以实现多个接口却不可以继承多个父类

QQ截图20120717221213.jpg (63.07 KB, 下载次数: 14)

QQ截图20120717221213.jpg

QQ截图20120717221104.jpg (37.74 KB, 下载次数: 24)

QQ截图20120717221104.jpg

评分

参与人数 1技术分 +1 收起 理由
刘笑 + 1 赞一个!

查看全部评分

回复 使用道具 举报
一般情况下,用Runnable接口
一是看起来好看,二,java是不能
多继承的。用Runnable接口后,还可以继承其它类

不过最后还得调用Thread 类



实现Runnable接口

Runnable接口中只定义了一个抽象方法
public void run();
格式:
class 类名称 implement Runnable  //实现Runnable接口
{
          属性...    //类中定义属性
          方法...    //类中定义方法
          public void run()  //覆写Runnable接口中的run()方法
          {
                   线程主体;
           }

}

例:
class MyThread implements Runnable //实现Runnable接口
{
             private String name;  //在类中定义一个属性
             public MyThread(String name) //定义一个构造方法
             {
                     this.name = name;
              }
             public void run()  //覆写Runnable接口中的run()方法
            {
                        for(int i = 0;i<10;i++)
                        {                     
                         System.out.println(name +"运行"+i)
                        }
             }
}

public class RunnableDemo
{
                public static void main(String[] args)
                {
                         MyThread my1 = new Mythread("线程A"); //实例化Runnable子类对象
                         MyThread my2 = new Mythread("线程B");

                         /*
                          要想启用一个多线程必须要使用start()方法完成,如果继承了
                         Thread类,可以直接使用用start()方法,但是现在实现了
                          Runnable接口,在Thread中提供了public Thread(Runnabel target)构造方法
                          就依靠此点来启动线程
                          */
                         Thread t1 = new Thread(my1);  //实例化Thread类对象
                         Thread t2 = new Thread(my2);
                          t1.start();    //启动线程
                          t2.start();
                    }
}


//打印结果


评分

参与人数 1技术分 +1 收起 理由
韦念欣 + 1 赞一个!

查看全部评分

回复 使用道具 举报
陈少文 发表于 2012-7-18 09:09
一般情况下,用Runnable接口
一是看起来好看,二,java是不能
多继承的。用Runnable接口后,还可以继承其它 ...

咋一看,我以为是看错了:实现Runnable接口怎么可能会出现会出两个线程拥有独立的资源?
建议LS以后不要再举这种例子了,以免本来对这个知识点模糊的人更模糊了
既然实现Runnable,肯定是考虑到需要资源共享,即实现多线程。而怎样实现多线程呢?肯定是只需要一个资源的对象。
你这里创建了共享资源的两个对象,又分别调用单独的线程跑,这样就显得实现Runnable和继承Thread类没有多大的区别。
这个例子继承Thread还可以让别人理解继承Thread类的弊端。                                       这种调用Runnable子类的方式就是把Runnable的优点覆盖掉了。
如果我也不懂,看了你的这段程序以后,就觉得继承Thread和实现Runnable根本没什么区别嘛!           所以要强调下实现Runnable是因为Runnable可以利用Thread(Runnable r)这个构造函数,只创建一个资源对象,实现多个线程资源共享,也就是上面我写的例子。至于java支持单继承只是其中很小的一个原因
回复 使用道具 举报
本帖最后由 王宝康 于 2012-7-18 12:07 编辑

其实这个问题可以从继承和实现的角度去看,
如果类 Zi 具有类 Fu 的全部属性和方法,而且又具有自己特有的某些属性和方法,则把类 Fu 称作一般类,把类 Zi 称作特殊类。
特殊类的对象拥有其一般类的全部或部分属性与方法,称作特殊类对一般类的继承,特殊类可以复写一般类的中的方法,

通过继承Thread类来创建线程其实就是运用了,子类复写父类的run()方法这个特性。

java中不允许多继承,也就是说类C同时具有类A和类B的全部属性和方法,类C只能继承其中之一,一个类只能有一个直接父类,但是可以实现多个接口,这时候就可以通过实现接口的方式来实现,你可以把你的类要提供的所有服务定义在接口中,而不提供实现,这样类C就可以通过实现接口来扩展自身的功能。

通过实现接口来创建线程呢,你就可以再去继承有针对性的其他类了,而只是通过实现Runnable接口来实现线程的运行。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马