首 页 网络编程
网页制作 图形图象 操作系统 冲浪宝典
软件教学 认证考试

网络安全 网络办公 行业资讯 评测对比
您当前位置:站长天空 -> 网页制作-> HTML教程
java 线程安全-JSP教程,Java技巧及代码
作者:网友供稿 点击:286
推荐
西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!可在线rar解压,自动数据恢复设置虚拟目录等.免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金
站内搜索
文章页数:[1] 
四种方式 sychronized关键字
sychronized method(){}
sychronized (objectreference) {/*block*/}
static synchronized method(){}
sychronized(classname.class)
其中1和2是代表锁当前对象,即一个对象就一个锁,3和4代表锁这个类,即这个类的锁
要注意的是sychronized method()不是锁这个函数,而是锁对象,即:如果这个类中有两个方法都是sychronized,那么只要有两个线程共享一个该类的reference,每个调用这两个方法之一,不管是否同一个方法,都会用这个对象锁进行同步。锁类的3和4类推,即该类的不同reference调用了sychronized区段的咚咚就会受类锁的控制

还有,如果两个函数调用的先后顺序不能被打断,那么可以有个专门的锁对象来完成这个任务:
class mylock
{
synchronized getlock()
{
//####还没写完
}
}


五个等级 参见effective java item 52 : document thread safety

immutable 不可变对象
thread-safe 线程安全的,可以放心使用,如java.util.timer
conditionally thread-safe 条件线程安全的,如vector和hashtable,一般是安全的,除非存在几个方法调用之间的顺序不能被打断,这时可以用额外的锁来完成
thread-compatible 可以使用synchronized (objectreference)来协助完成对线程的调用
thread-hostile 不安全的

wait & notifyall

在循环中使用wait 使用notifyall而不是notify

pipe

java中也有pipe的,四个类:pipedinputstream, pipedinputreader, pipedoutputstream, pipedoutputwriter 下面是一段生产者消费者的代码(摘自core javaii):

/* set up pipes */
pipedoutputstream pout1 = new pipedoutputstream();
pipedinputstream pin1 = new pipedinputstream(pout1);
pipedoutputstream pout2 = new pipedoutputstream();
pipedinputstream pin2 = new pipedinputstream(pout2);
/* construct threads */
producer prod = new producer(pout1);
filter filt = new filter(pin1, pout2);
consumer cons = new consumer(pin2);
/* start threads */
prod.start(); filt.start(); cons.start();



注意

long 和double是简单类型中两个特殊的咚咚:java读他们要读两次,所以需要同步
死锁是一个经典的多线程问题,因为不同的线程都在等待那些根本不可能被释放的锁,从而导致所有的工作都无法完成。假设有两个线程,分别代表两个饥饿的人,他们必须共享刀叉并轮流吃饭。他们都需要获得两个锁:共享刀和共享叉的锁。假如线程 "a" 获得了刀,而线程 "b" 获得了叉。线程 a 就会进入阻塞状态来等待获得叉,而线程 b 则阻塞来等待 a 所拥有的刀。这只是人为设计的例子,但尽管在运行时很难探测到,这类情况却时常发生。虽然要探测或推敲各种情况是非常困难的,但只要按照下面几条规则去设计系统,就能够避免死锁问题:

让所有的线程按照同样的顺序获得一组锁。这种方法消除了 x 和 y 的拥有者分别等待对方的资源的问题。

将多个锁组成一组并放到同一个锁下。前面死锁的例子中,可以创建一个银器对象的锁。于是在获得刀或叉之前都必须获得这个银器的锁。

将那些不会阻塞的可获得资源用变量标志出来。当某个线程获得银器对象的锁时,就可以通过检查变量来判断是否整个银器集合中的对象锁都可获得。如果是,它就可以获得相关的锁,否则,就要释放掉银器这个锁并稍后再尝试。

最重要的是,在编写代码前认真仔细地设计整个系统。多线程是困难的,在开始编程之前详细设计系统能够帮助你避免难以发现死锁的问题。
volatile 变量. volatile 关键字是 java 语言为优化编译器设计的。以下面的代码为例:
class volatiletest {

public void foo() {
boolean flag = false;

if(flag) {
//this could happen
}
}
}




一个优化的编译器可能会判断出 if 部分的语句永远不会被执行,就根本不会编译这部分的代码。如果这个类被多线程访问, flag 被前面某个线程设置之后,在它被 if 语句测试之前,可以被其他线程重新设置。用 volatile 关键字来声明变量,就可以告诉编译器在编译的时候,不需要通过预测变量值来优化这部分的代码。




无法访问的线程 有时候虽然获取对象锁没有问题,线程依然有可能进入阻塞状态。在 java 编程中 io 就是这类问题最好的例子。当线程因为对象内的 io 调用而阻塞时,此对象应当仍能被其他线程访问。该对象通常有责任取消这个阻塞的 io 操作。造成阻塞调用的线程常常会令同步任务失败。如果该对象的其他方法也是同步的,当线程被阻塞时,此对象也就相当于被冷冻住了。其他的线程由于不能获得对象的锁,就不能给此对象发消息(例如,取消 io 操作)。必须确保不在同步代码中包含那些阻塞调用,或确认在一个用同步阻塞代码的对象中存在非同步方法。尽管这种方法需要花费一些注意力来保证结果代码安全运行,但它允许在拥有对象的线程发生阻塞后,该对象仍能够响应其他线程。

调用 yield() 方法能够将当前的线程从处理器中移出到准备就绪队列中。另一个方法则是调用 sleep() 方法,使线程放弃处理器,并且在 sleep 方法中指定的时间间隔内睡眠。
正如你所想的那样,将这些方法随意放在代码的某个地方,并不能够保证正常工作。如果线程正拥有一个锁(因为它在一个同步方法或代码块中),则当它调用 yield() 时不能够释放这个锁。这就意味着即使这个线程已经被挂起,等待这个锁释放的其他线程依然不能继续运行。为了缓解这个问题,最好不在同步方法中调用 yield 方法。将那些需要同步的代码包在一个同步块中,里面不含有非同步的方法,并且在这些同步代码块之外才调用 yield。

另外一个解决方法则是调用 wait() 方法,使处理器放弃它当前拥有的对象的锁。如果对象在方法级别上使同步的,这种方法能够很好的工作。因为它仅仅使用了一个锁。如果它使用 fine-grained 锁,则 wait() 将无法放弃这些锁。此外,一个因为调用 wait() 方法而阻塞的线程,只有当其他线程调用 notifyall() 时才会被唤醒。

在进行多线程编程时,经常要使用同步互斥机构,但java本身没有提供的同步互斥机构,仅提供了两个与同步互斥有关的方法:wait()和notify(),可以用来设计信号量类:mysemaphore,它是按照dijkstra提出的计数信号量的思想设计的。

mysemaphore有两个最重要的成员方法:p()和v()。这两个方法实际就实现了信号量的p操作和v操作。具体描述如下:

public synchronized void p(){

semaphore--;

if(semaphore<0){

try{

wait();

}catch(interruptedexception ie){}

}

}

public synchronized void v(){

semaphore++;

if(semaphore<=0)

notify();

}

其中,semaphore变量记录了信号量的状态,wait()方法相当于block原语,用于阻塞线程的执行,notify()方法相当于wakeup原语,用于唤醒线程恢复运行。由于这两个方法定义为synchronized,这样java虚拟机可保证这两个方法的原子执行,从而实现了p、v操作。

二、管道

并发程序的多个线程之间的通讯通常是使用管道进行,jdk提供了两个管道类:pipedinpustream和pipedoutputstream,前者用于输入,后者用于输出。这两种管道应该是能够多次连接和关闭,在实现过程中,却发现它们在关闭后,不能重新建立连接。经过仔细调试后,发现jdk的源代码在处理关闭时释放资源存在着缺陷,因此需要编写自己的管道类:mypipedinputstream和mypipedoutputstream。这两个类直接从inputstream和outputstream继承而来,其成员方法与实现基本与pipedinputstream和pipedoutputstream一致,只是在处理关闭时,将类中的成员变量的值恢复成未连接时的初始值。另外,原有的管道了提供的管道容量只有1024个字节,在传输数据量较大时,可能会发生溢出,而在自己的管道类中可以任意设置管道容量,例如可以根据需要把管道容量设为64kb。以下仅给出了相应的关闭例程:

1.mypipedinputstream

public void close() throws ioexception {

in = -1;

out = 0;

closedbyreader = true;

connected = false;

closed = true;

buffer = new byte[pipe_size];

}

2.mypipedoutputstream

public void close() throws ioexception {

if (sink != null) {

sink.receivedlast();

sink.closed = true;

}

sink = null;

connected = false;

}



文章整理:站长天空 网址:http://www.z6688.com/
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

文章页数:[1] 


放大字体显示 缩小字体显示 打印文章 推荐给朋友
热门文章
·C#时间函数扩展-.NET教程,C#语言
·成人影片女明星jameson推出手机情色铃声服务
·窗体中控件自动随窗体变化大小-.NET教程,组件控件开发
·C#使用CDO发送邮件-.NET教程,C#语言
·浅析nat的类型
·我的字符和文件加密类,128位加密-.NET教程,评论及其它
·数字机顶盒技术综述 (一)
·数字多媒体广播平台及其关键技术
·java 线程安全-JSP教程,Java技巧及代码
·Remoting和Web服务的区别-.NET教程,Web Service开发
最新文章
·如何通过博客月赚几万美金?_网赚技巧
·浅析广告联盟与个人网站的盈利_网赚技巧
·google adsense会议的主要内容回顾_网赚技巧
·赵克:创业基本素质勤奋专业低调务实_站长访谈
·行业网站分析之一:行业网站现状与前景_站长心得
·分享:做网站月入7000的网站赚钱经验_站长心得
·首页所应该达到的几个目标(2)_站长心得
·google sandbox效应_google推广
·google旧瓶装新酒 用遗弃技术开发web新应用_google推广
·认识google优化排名_google推广
相关主题
  • java mail线上教学_邮件服务器
  • java MD5算法返回数字型字串-JSP教程,Java技巧及代码
  • Java 语言中的 return 语句-JSP教程,Java技巧及代码
  • java Logging API 使用-JSP教程,Java技巧及代码
  • java 中protected modifier 使用总结-JSP教程,Java技巧及代码
  • 西部数码虚拟主机

    友情链接
    CNNIC 西部数码
    万网 自助建站
    虚拟主机 asp空间
    域名注册 域名
    域名申请 主页空间
    论坛空间 网站空间
    国际域名 虚拟空间
    空间租用 DDOS防火墙
    成都主机托管 四川主机托管
    主机租用 服务器租用
    网站目录 自助建站
    虚拟主机 网址大全
    软件下载
    自助链接
    虚拟主机资讯 特价虚拟主机
    版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
    关于我们:站长天空:专业提供最新的站长资讯、在线教程、虚拟主机权威评测、虚拟主机性能对比、网站制作教程,开发教程,站长工具。包括网页制作教程、冲浪宝典、编程参考、操作系统、软件教学、行业动态等。
    特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
    发表评论 打印  刷新     关闭