加载中…
正文 字体大小:

2011腾讯java笔试一道线程探讨

(2011-04-24 09:52:49)
标签:

腾讯面试题

it

TX的笔试,java的附加题是一道线程之间通信的问题。要求是:1线程之间不可相互访问对方的变量。2、可以访问公有的byte[]数组 3 设计一个程序 使得两个线程A和B,A把一个对象告诉B,然后B把对象的值打印出来。

咋一看貌似挺简单,但是涉及了对象的序列化与反序列化,线程之间的通信与同步。

当 时我的做法是,写了两个线程类A和B,一个ThreadPool类,A和B的实例创建都要放进ThreadPool里。A在它的生命周期里负责在 ThreadPool获取出B的实例,调用其提供的setXXX方法将对象传入,B则一直等待XXX的传入,一旦传入,就结束循环,将值打印。这样的做法 显然不符合第一个要求,而且也没用到提供的byte数组,感觉怪怪的。于是今晚经过一番调研之后,重新写了一遍。代码如下:

 //线程通信数据类,实现Serializable接口以便序列化

class Employee implements java.io.Serializable {

 

    private String name;

 

    public Employee(String name) {

        this.name = name;

    }

 

 

    public String getName() {

        return name;

    }

   

    public void setName(String name) {

        this.name = name;

    }

}

 

class A extends Thread {

 

    private static byte[] b = new byte[255]; //公用数据区

 

    public A(String name) {

        super(name);

    }

 

    public void run() {

        if (this.getName().equals("A")) {

            synchronized (b) { //将b加锁

                try {

                    b = ByteUtil.getBytes(new Employee("pany"));//new 一个E对象并序列化成字节数组

                    System.out.println("in A");

                    sleep(2000);

                } catch (InterruptedException ex) {

                    Logger.getLogger(A.class.getName()).log(Level.SEVERE, null, ex);

                } catch (IOException ex) {

                    Logger.getLogger(A.class.getName()).log(Level.SEVERE, null, ex);

                }

            }

        } else if (this.getName().equals("B")) {

            synchronized (b) {

                try {

                    Employee e = (Employee) ByteUtil.getObject(b);//反序列化为E

                    System.out.println(e.getName());

                    sleep(2000);

                } catch (InterruptedException ex) {

                    Logger.getLogger(A.class.getName()).log(Level.SEVERE, null, ex);

                } catch (IOException ex) {

                    Logger.getLogger(A.class.getName()).log(Level.SEVERE, null, ex);

                } catch (ClassNotFoundException ex) {

                    Logger.getLogger(A.class.getName()).log(Level.SEVERE, null, ex);

                }

            }

        }

 

    }

 

public class MyThread {

 

    public static void main(String[] args) {

        A a = new A("A");

        A b = new A("B");

        a.start();

        b.start();

    }

}

 

 //工具类,序列化对象与反序列化对象

class ByteUtil {

 

    public static byte[] getBytes(Object obj) throws IOException {

        ByteArrayOutputStream bout = new ByteArrayOutputStream();

        ObjectOutputStream out = new ObjectOutputStream(bout);

        out.writeObject(obj);

        out.flush();

        byte[] bytes = bout.toByteArray();

        bout.close();

        out.close();

 

        return bytes;

    }

 

    public static Object getObject(byte[] bytes) throws IOException, ClassNotFoundException {

        ByteArrayInputStream bi = new ByteArrayInputStream(bytes);

        ObjectInputStream oi = new ObjectInputStream(bi);

        Object obj = oi.readObject();

        bi.close();

        oi.close();

        return obj;

    }

}

上述代码中,当名字为A的线程运行时,先对b加锁,使得这段时间内其他线程无法访问到b。然后将Employee对象序列化后存在b中,运行结束后释放b的锁,使得其他线程(B)可获得b的锁,然后进行相关操作。

 

但是,上面这段代码在运行的过程中有可能会出错,因为以下代码:

        A a = new A("A");

        A b = new A("B");

        a.start();

        b.start();

虽 然a.start()的调用比b.start()的调用早,但是,线程调用了start()方法之后,进入就绪态,而非运行态,它必须被OS选择并分配时 间片后方可运行。显然,你永远都不知道a和b哪个先被系统选择运行。所以上面的方法很有可能在b未存储任何Employee对象的时候,B线程去反序列化 它!因此我们必须保证A比B先进入运行态,可以通过下面的方法改进:

        A a = new A("A");

        A b = new A("B");

        a.start();

        try {

            a.join(); //join()方法表示等待该线程结束

        } catch (InterruptedException ex) {

            Logger.getLogger(MyThread.class.getName()).log(Level.SEVERE, null, ex);

        }

        b.start();

0

阅读 评论 收藏 转载 喜欢 打印举报
已投稿到:
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4006900000 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有