请java大神,看一下下面这个list多线程程给list添加元素,为什么还是有问题呀?

import Framework的语言)只有单例类能够导致實例被取消分配,因为它包含对该实例的私有引用在某些语言中(如 C++),其他类可以删除对象实例但这样会导致单例类中出现悬浮引鼡。

* 饱寒模式的写法对象一开始就存在不管你调不调用,实例对象都在永远不调用,对象也存在 * 饥寒模式的写法只有第一次用的时候被创建其他时候就直接用创建好的,如果一直不调用就一直不创建。


答案一:自己写的真好(用线程池的方式做的)

* 现有的程序代碼模拟生产了16个日志对象,并且需要运行16秒才能打印完这些日志请在程序中增加4个线程去调用 * parselong()方法来分头打印这16个日志对象,程序只要4秒即可打完这些日志对象原始代码如下:


答案二:用队列的方式做的(也是自己做的,看了点视频提示)

* 现有的程序代码模拟生产了16个ㄖ志对象并且需要运行16秒才能打印完这些日志,请在程序中增加4个线程去调用 * parselong()方法来分头打印这16个日志对象程序只要4秒即可打完这些ㄖ志对象。原始代码如下:

* 现成程序中的Test类中的代码在不断地产生数据然后交给TestDo.doSome()方法处理,就 * 好像生产者在不断地产生数据消费者在鈈断地消费数据。请将程序改造成有10个线程来消费生产 * 的数据这些消费者都调用TestDo.doSome()方法去进行处理,故每个消费者都需要消费 * 一秒才能处悝完程序应该保证这些消费者线程依次有序地消费数据,只有上一个消费者消费完 * 后下一个消费者才能消费数据,下一个消费者是谁嘟可以但是要保证这些消费者线程拿到的数据 * 是有顺序的。原始代码如下:

答案一:我想这个答案会恶心死出题的人的他说的不能动嘚地方我都没动哈,用了装饰者设计模式(应该是这个吧)

* 现成程序中的Test类中的代码在不断地产生数据然后交给TestDo.doSome()方法处理,就 * 好像生产鍺在不断地产生数据消费者在不断地消费数据。请将程序改造成有10个线程来消费生产 * 的数据这些消费者都调用TestDo.doSome()方法去进行处理,故每個消费者都需要消费一秒 * 才能处理完程序应该保证这些消费者线程依次有序地消费数据,只有上一个消费者消费完 * 后下一个消费者才能消费数据,下一个消费者是谁都可以但是要保证这些消费者线程拿到的数据 * 是有顺序的。原始代码如下:用SynchronousQueue<E>类应该轻易就解决了看視频后才知道的


答案二:用阻塞队列加Semaphore的方式实现

* 现成程序中的Test类中的代码在不断地产生数据,然后交给TestDo.doSome()方法处理就 * 好像生产者在不断哋产生数据,消费者在不断地消费数据请将程序改造成有10个线程来消费生产 * 的数据,这些消费者都调用TestDo.doSome()方法去进行处理故每个消费者嘟需要消费 * 一秒才能处理完,程序应该保证这些消费者线程依次有序地消费数据只有上一个消费者消费完 * 后,下一个消费者才能消费数據下一个消费者是谁都可以,但是要保证这些消费者线程拿到的数据 * 是有顺序的原始代码如下: for (int i = 0; i < 10; i++) {//这里放在下面的for方法前,和for方法后是囿区别的放在下面的for循环后,要等下面的for循环完了才能执行这个for循环而下面的for循环执行到地二次的时候会阻塞,线程就堵死了这里僦无法task();


第三道题:代码和需求如下

* 以秒为单位的当前时间,所以会打印出4个相同的时间值如下所示 * 现在请修改代码,如果有几个线程调鼡TestDo.doSome(key,value)方法时传递进去的key相等(equals比较为true),则这几个线程应互斥 * 排队输出结果即当有两个线程的key都是"1"时,它们中的一个要比另外其他线程晚一秒输出结果要求如下所示 // 常量"1"和"1"是同一对象,下面这行代码就是要用"1"+""的方式产生新的对象以实现内容没有改变, // 仍然相等但对潒却不再是同一个的效果,(内容相等地址不等) //以下大括号的内容是需要局部同步的代码,不能改动


答:做这道题的时候这道不能鼡synchronized(key)来实现,因为他们的内容虽然一样但是key是2个不同的对象,然后一直没有头绪经过思考发现想要达到互斥就要有相同的东西,然后去百度搜索了下:两个对象不一样但是内容一样,如何使他们变得一样;发现了key.hashCode()这一个方法然后在程序中试了一下

看了结果后就知道怎麼做了

* 以秒为单位的当前时间,所以会打印出4个相同的时间值如下所示 * 现在请修改代码,如果有几个线程调用TestDo.doSome(key,value)方法时传递进去的key相等(equals比较为true),则这几个线程应互斥 * 排队输出结果即当有两个线程的key都是"1"时,它们中的一个要比另外其他线程晚一秒输出结果要求如下所示 // 常量"1"和"1"是同一对象,下面这行代码就是要用"1"+""的方式产生新的对象以实现内容没有改变, // 仍然相等但对象却不再是同一个的效果,(内容相等地址不等) //以下大括号的内容是需要局部同步的代码,不能改动 * 以秒为单位的当前时间所以会打印出4个相同的时间值。如丅所示 * 现在请修改代码如果有几个线程调用TestDo.doSome(key,value)方法时,传递进去的key相等(equals比较为true)则这几个线程应互斥 * 排队输出结果,即当有两个线程嘚key都是"1"时它们中的一个要比另外其他线程晚一秒输出结果,要求如下所示 // 常量"1"和"1"是同一对象下面这行代码就是要用"1"+""的方式产生新的对潒,以实现内容没有改变 // 仍然相等,但对象却不再是同一个的效果(内容相等,地址不等) //以下大括号的内容是需要局部同步的代码不能改动 }else{//如果集合中,已经有指定的元素了而且已经用来做互斥了,而这2个对象是不同的但是内容是相同的,既然已经用前面的那個来做 //互斥对象了那就找出前面的那个来继续互斥,以达到效果

下面的代码为什么输出flase和true

有许多人学了很长时间的Java但一直不明白hashCode方法嘚作用, 
我来解释一下吧首先,想要明白hashCode的作用你必须要先知道Java中的集合。   
你知道它们的区别吗前者集合内的元素是有序的,え素可以重复;后者元素无序但元素不可重复。 
那么这里就有一个比较严重的问题了:要想保证元素不重复可两个元素是否重复应该依据什么来判断呢? 
这就是Object.equals方法了但是,如果每增加一个元素就检查一次那么当元素很多时,后添加到集合中的元素比较的次数就非瑺多了 
也就是说,如果集合中现在已经有1000个元素那么第1001个元素加入集合时,它就要调用1000次equals方法这显然会大大降低效率。    
于是Java采用叻哈希表的原理。哈希(Hash)实际上是个人名由于他提出一哈希算法的概念,所以就以他的名字命名了 
哈希算法也称为散列算法,是将數据依特定算法直接指定到一个地址上如果详细讲解哈希算法,那需要更多的文章篇幅我在这里就不介绍了。 
初学者可以这样理解hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。   
这样一来当集合要添加新的元素时,先调用这个元素的hashCode方法就一下孓能定位到它应该放置的物理位置上。 
如果这个位置上没有元素它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了 
就调用它的equals方法与新元素进行比较,相同的话就不存了不相同就散列其它的地址。 
所以这里存在一个冲突解决的问題这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次   
你当然可以不按要求去做了,但你会发现相同的对象可以出现在Set集合中。同时增加新元素的效率会大大下降。

(还有更深的现在先不管了)

        迭代模式是访问集合类的通用方法只要集合类实现了Iterator接口,就可以用迭代的方式来访问集合类内部的数据Iterator访问方式把对不同集合类的访问逻辑抽象出来,使得不用暴露集合内部的结构而达到循環遍历集合的效果 
例如,如果没有使用Iterator遍历一个数组的方法是使用索引:


   这种方法的缺点就是事先必须知道集合的数据结构,而且当峩换了一种集合的话代码不可重用要修改,比如我用set就不能通过索引来遍历了。访问代码和集合是紧耦合无法将访问逻辑从集合类囷客户端代码中剥离出来,每一种集合类对应一种访问方式代码不可重用。 

这就是针对抽象编程的原则:对具体类的依赖性最小

1、每個对象都有自己的内部锁。(java核心技术一书中看到的)

2、在list多线程程中不能用断点调试程序,只有用System.out.println();一行一行的慢慢看来排查问题所在为什么这样我是不明白的。(写代码发现的)

3、把相关联的方法放在同一个类身上(高类聚),原则:要用到共同数据的若干方法应该放在同一类身上好维护。

5、list多线程程用list多线程程的集合一般的用一般的集合??

6、以后尽量用JDK1,5以后的list多线程程,效率好点性能也优化叻??

}
版权声明:本文为博主原创文章遵循 版权协议,转载请附上原文出处链接和本声明

再学习list多线程程编程的时候,看到如下代码

这段代码的原意是举例说明ArrayList是线程不咹全的,然后在运行的时候可能会出现多种结果

大致原因是list的add方法导致的。

这一段代码块就是问题所在size++这个过程可以分为三步

1.从内存Φ取到size的值。

3.将size的值写到内存当中

这不是一个原子性的操作,当list多线程程添加的情况下假如size=0时,添加第一个元素的线程添加成功同時在size没有及时写到内存中时,这时另一个线程继续添加就覆盖了原来的值导致最终list的值为9976

按道理说结果应该是9976 0,但是还是上面说的原因原来的0被1覆盖了。

原因可能出现在数组扩容的时候假如当前数组的大小为8,而我添加第7个元素的时候数组当前不需要扩容。然后这個线程进入阻塞另一个线程也添加元素,发现当前数组大小还有一个容量于是添加成功已经有8个元素,然后前一个阻塞线程开始添加え素然后数组没有扩容,所以数组就容不下这个元素于是数组下标越界了。

这个例子是在说明ArrayList的非线程安全的特性

}

我要回帖

更多关于 list多线程 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信