摘要:
线程中是可以再添加其他线程,这是通过添加join()方法,但是效果确实等待一段时间直到第二个线程结束才继续执行。如果某个线程在另一个线程t上调用t.join(),此线程将会被挂起,直到目标线程t结束才恢复。对join()方法的调用可以被中断,就是在调用线程上调用interrupt()方法,这时就需要try-catch子句。 阅读全文
posted @ 2012-08-28 17:23
文酱
阅读(688)
评论(0)
推荐(0)
摘要:
所谓的阻塞,就是线程能够运行,但是某个条件阻止它的运行,当线程处于阻塞状态时,调度器将忽略线程,不会分配给线程任何CPU时间,直到线程重新进入就绪状态,它才有可能执行操作。就绪并代表是在运行啊,所谓的就绪,就是可运行也可不运行,只要调度器分配时间片给线程,线程就可以运行,因为我们都知道,调度器是如何分配线程,是不确定的。为什么任务会进入阻塞的状态,一般有以下几个原因: 1.通过调用sleep(milliseconds)使任务进入休眠状态,在这种情况下,任务在指定的时间内不会运行; 2.通过调用wait()使线程挂起,直到线程得到了notify()或notifyAll()消息(或者... 阅读全文
posted @ 2012-08-28 17:22
文酱
阅读(12855)
评论(1)
推荐(0)
摘要:
线程的终止其实很简单,只要在实现Runnable的类中添加cancel()方法和cancel标记。如: private static volatile boolean canceled = false; public static void cancel(){ canceled = true;} 注意,这里是volatile标记的static布尔值,因为这是接下来的方法中都会用到的,而且其值的变化会对它们产生影响,所以是static。volatile就像之前说过的,标记这个布尔值为共享的,使得接下来的与其有直接或者间接的synchronized方法都能看到它的变化,然后就是设置一... 阅读全文
posted @ 2012-08-28 17:21
文酱
阅读(260)
评论(0)
推荐(0)
摘要:
在任务的协作中,是需要任务间的协议,而这份协议,正如之前所说的,正是通过锁来实现。但是,有时候,这协议会错失,就是没有被其他任务正确的接收到。信号的错失会导致错误,所以,我们要为避免信号错失而做出努力,因为信号的错失是可能导致出现死锁的,只要是使用锁,就要避免出现死锁这种局面。这问题的解决方案就是防止在唤醒条件上产生竞争,因为很多时候的错失都是因为对唤醒条件的竞争,如:T1: synchronized(sharedMonitor){ <setup condition for T2> sharedMonitor.notify(); } T2: while(som... 阅读全文
posted @ 2012-08-28 17:20
文酱
阅读(302)
评论(0)
推荐(0)
摘要:
什么是死锁?死锁就是这样的情况,某个任务在等待另一个任务,而后者又在等待别的任务,这样一直下去,直到这个链条上的任务又在等待第一个任务释放锁。这就是一个任务间互相等待的连续循环,没有哪个线程能继续。死锁的可怕并不在于它马上发生,可怕的是任何加锁的程序够可能发生死锁的危险。防止死锁是设计并发编程一开始就必须考虑的事情。要防止死锁,就必须知道死锁的发生条件。 会产生死锁必须满足一下四个条件: 1.互斥条件。任务在使用的资源中至少有一个是不可能共享的; 2.至少有一个任务它必须持有一个资源且正在等待获取一个当前被别的任务持有的资源; 3.资源不能被任务抢占,任务必须把资源释放当做普... 阅读全文
posted @ 2012-08-28 17:19
文酱
阅读(282)
评论(0)
推荐(0)
摘要:
任务不仅是只有竞争的关系,还有协作。所谓的协作,就是一般意义上的协作,多个任务同时完成同一个问题的各个部分。所以,现在问题已经不是任务间的干涉,而是任务间的协调。因为在这类问题中,某些部分必须在其他部分被解决前解决,而且,在这些任务中,某些是可以并发执行的。某些甚至是所有任务都结束后进行,就像建房子一样,总得建完地基后才能开始往上建吧。 所以,任务的协作的关键就是任务间的协议。怎样才能实现这种协议呢?还是使用互斥,也就是锁。没错,你没有看错,就是使用锁来实现协作。为什么可以呢?明明协作与竞争在字面上来说,应该是相反的啊,但是基本构成是可以一样的啊。因为锁能够确保只有一个任务可以响应某个信号.. 阅读全文
posted @ 2012-08-28 17:19
文酱
阅读(304)
评论(0)
推荐(0)
摘要:
到底什么时候该同步呢?这个问题的实际意义很强,但是又说不准,因为并发这块说真的,意外性太多了,很多情况都是我们在不知道下莫名其妙发生。有一个原则,就是若一个变量接下来可能被另一个线程读取,或正在读取一个上一次已经被另一个线程写过的变量,那么,必须使用同步,并且,读写线程都必须用相同的锁同步。所以,若在类中有超过一个方法在处理同步数据,那么必须同步所有相关方法,这是最安全的方法,千万不要嫌麻烦,若没有这么做,以后要是出现什么未知错误,那时头更大呢。 阅读全文
posted @ 2012-08-28 17:18
文酱
阅读(283)
评论(0)
推荐(0)
摘要:
如果我们希望防止多个线程同时访问方法内部的部分代码而不是防止访问整个方法,通过这种方式分离出来的代码段被称为临界区。那么怎么建立临界区?这时就需要关键字synchronized。synchronized必须先指定某个对象,获得该对象的锁,来用来对花括号内的代码进行同步控制,如: synchronized(syncObject){...} 这就是同步控制块,也就是临界区。那么,一如既往的问题就来了,为什么需要同步控制块?同步控制块有什么好处?同步控制块的一个显著的优点就是可以使多个任务访问对象的时间性能得到显著提高,这个性能的体现就在于加锁的时间,同步整个方法,那么在这整个方法执行完前,... 阅读全文
posted @ 2012-08-28 17:17
文酱
阅读(332)
评论(0)
推荐(0)
摘要:
在并发编程中,线程的概念是非常重要的。说到线程,自然就要提到进程。下面就先厘清这两个概念。进程是运行在自己的地址空间内的自包容的程序,线程是在进程中的一个单一的顺序控制流。因此,单个进程是可以拥有多个线程。所以,这里我们可以知道,进程和线程的区别。 线程是很容易让人跟任务混在一起,事实上,两者根本不是同一个东西,只是经常捆在一起讲。准确的说,任务是由执行线程来驱动的,任务是附着在线程上的。 如何创建线程呢?首先我们必须先定义我们的任务,因为线程是驱动任务的,没有搭乘的任务,就谈不上要去创建线程,就像列车开动,必须指明目的地,否则列车要怎么开啊。定义任务的方式很简单,就是一个实现Run... 阅读全文
posted @ 2012-08-28 17:16
文酱
阅读(294)
评论(0)
推荐(0)
摘要:
volaatile关键字是java中同步机制中一个非常重要的关键字,它保证了可视性。如果一个域被声明为volatile,那么只要对这个域产生写操作,那么所有的读操作都可以看到这个修改。这就是同步,在并发中是非常重要的。如果资源被某个任务修改,但是其他读取这个资源的任务并不知道,那么是会发生问题的,就像你老婆怀孕了,但是在你知道这个消息前,你并不知道她和其他男人上过,那么你得到这个怀孕的消息时,就会发生严重的问题,孩子可能不是你的,但是你并不知道啊!撇开这个我胡乱编造的例子,大家应该可以知道同步的重要性了吧,尤其是男人。 并不是所有对某个域有写操作就要声明为volatile,像是一个任务的... 阅读全文
posted @ 2012-08-28 17:15
文酱
阅读(299)
评论(0)
推荐(0)
摘要:
这个问题首先必须知道的是,多个任务同时访问同一个资源会出现什么问题?这是很关键的事情,因为如果我们不知道为什么会出现问题,而且也不知道问题是什么样子,就好像是明知对面浓雾里有致命的敌人,但是却无法知道敌人长什么样子,也不知道会从哪里冒出来,说真的,这种感觉很要命,一点也不好玩!那么,我们的敌人到底是谁呢? 多个任务同时竞争同一个资源,就像两个大胖子抢一个浴缸,两辆车抢同一个车位,等等,在现实生活中,这些情况一定会发生严重的争执,而在程序中,就是在运行中,我们永远不知道到底是哪个任务得到资源。哦,真要命,作为程序员,最害怕的情况之一就是我们竟然无法得知自己程序的运行情况!相信每个程序... 阅读全文
posted @ 2012-08-28 17:11
文酱
阅读(2008)
评论(0)
推荐(0)
摘要:
内部类的构造器必须连接到指向其外围类对象的引用,所以继承内部类时,必须初始化这个引用,而在导出类中,与外围类对象默认的连接必须断绝,以保持外围类与导出类的独立性。如:class InheritInner extends WithInner.Inner{ InheritInner(WithInner with){ with.super(); }}这没有什么好惊讶的,因为内部类的构造器本来就是外围类的,所以导出类的构造器中是明确的将外围类的构造器作为其构造器,这样就只是得到外围类的构造器而并没有得到更多的东西。 阅读全文
posted @ 2012-08-28 17:03
文酱
阅读(220)
评论(0)
推荐(0)
摘要:
内部类能否在其可见域内定义static数据或方法呢?答案是不行的。为什么呢?想想就知道了,static数据和方法有种说法,叫做类数据和类方法,为什么这么叫?因为他们是作为类的组成部分,在层次上,是与方法等同的地位,因此,内部类是不能拥有static数据和方法的,就像方法不能拥有static一样。但是嵌套类可以。什么是嵌套类?嵌套类就是加上static修饰的内部类,嵌套类的行为和内部类大相径庭,甚至在根本上已经和内部类不一样,但是如果说,只要放在一个类里面定义的类,就是内部类,那么嵌套类确实可以叫做内部类。嵌套类最大的区别,就是它没有外围类的引用!这点在讲static时,就说过,stat... 阅读全文
posted @ 2012-08-28 17:02
文酱
阅读(255)
评论(0)
推荐(0)
摘要:
内部类为什么能够访问外围类的成员?这个问题是很基本的问题,但是基本归基本,确是很重要,急需解决的问题,因为不明白这个问题,对于内部类本身也会存在很多困扰。内部类能够访问外围类,这是因为内部类有一个指向外围类对象的引用。因为内部类的创建是需要先创建外围类的实例的,内部类在外围类的组成层次上相当于外围类的方法。但是更重要的是,内部类是可以访问外围类的所有成员,包括私有的,这一点正像前面所讲的,因为内部类在创建时需要先创建外围类的实例并取得对其的引用,所以,自然,外围类的所有成员对于内部类来说是公开的。有什么证据能够证明呢?证据就是我们能够在内部类中返回外围类的引用,如:OuterClass... 阅读全文
posted @ 2012-08-28 16:59
文酱
阅读(281)
评论(0)
推荐(0)
摘要:
内部类,是java中“哇”的特性之一。为什么说它是"哇“,因为每个刚接触的人都一定会说,”哇!“,怎么会有这种奇怪的东西。是的,这的确是一个令人会”哇"的东西,更重要的是,它并不是语言设计者在语言设计上的一个小花招,它的出现,是为了解决java中如何更好的实现多重继承但是又不会出现C++中出现的一些麻烦,而且也确实很好的解决了这个问题。 C++的多重继承是很难用的东西,因为很难保证它的继承行为不会带来问题,尤其是继承的层次越多,就越会出现问题。java作为C++的继承者,自然也在这方面做了非常大的努力,毕竟多重继承的作用依然是相当吸引人的,是不能随便放弃的。 再次强调,这篇 阅读全文
posted @ 2012-08-28 16:56
文酱
阅读(757)
评论(0)
推荐(0)