jacob合并几个word文件到一个word文件

Posted on

jacob合并几个word文件到一个word文件

 因项目需要将几个word文件合并到一个word文件,后面附项目运用的jar包jacob-1.9

jacob运用中,需要将附件内的jacob.dll放到windows/system32下

 直接上代码:

Java代码 收藏代码

  1. public static void main(String[] args) {
  2. List list = new ArrayList();
  3. String file1= "D:\file1.doc";
  4. String file2= "D:\file2.doc";
  5. String file3= "D:\file3.doc";
  6. list.add(file1);
  7. list.add(file2);
  8. list.add(file3);
  9. uniteDoc(list,"d:\file.doc");
  10. }
  11. public static void uniteDoc(List fileList, String savepaths) {
  12. if (fileList.size() == 0 || fileList == null) {
  13. return;
  14. }
  15. //打开word
  16. ActiveXComponent app = new ActiveXComponent("Word.Application");//启动word
  17. try {
  18. // 设置word不可见
  19. app.setProperty("Visible", new Variant(false));
  20. //获得documents对象
  21. Object docs = app.getProperty("Documents").toDispatch();
  22. //打开第一个文件
  23. Object doc = Dispatch
  24. .invoke(
  25. (Dispatch) docs,
  26. "Open",
  27. Dispatch.Method,
  28. new Object[] { (String) fileList.get(0),
  29. new Variant(false), new Variant(true) },
  30. new int[3]).toDispatch();
  31. //追加文件
  32. for (int i = 1; i < fileList.size(); i++) {
  33. Dispatch.invoke(app.getProperty("Selection").toDispatch(),
  34. "insertFile", Dispatch.Method, new Object[] {
  35. (String) fileList.get(i), "",
  36. new Variant(false), new Variant(false),
  37. new Variant(false) }, new int[3]);
  38. }
  39. //保存新的word文件
  40. Dispatch.invoke((Dispatch) doc, "SaveAs", Dispatch.Method,
  41. new Object[] { savepaths, new Variant(1) }, new int[3]);
  42. Variant f = new Variant(false);
  43. Dispatch.call((Dispatch) doc, "Close", f);
  44. } catch (Exception e) {
  45. throw new RuntimeException("合并word文件出错.原因:" + e);
  46. } finally {
  47. app.invoke("Quit", new Variant[] {});
  48. }
  49. }

public static void main(String[] args) {

        List list  = new ArrayList();
        String file1= "D:\\file1.doc";

        String file2= "D:\\file2.doc";
        String file3= "D:\\file3.doc";

        list.add(file1);
        list.add(file2);

        list.add(file3);
        uniteDoc(list,"d:\\file.doc");

}
public static void uniteDoc(List fileList, String savepaths) {

    if (fileList.size() == 0 || fileList == null) {
        return;

    }
    //打开word

    ActiveXComponent app = new ActiveXComponent("Word.Application");//启动word
    try {

        // 设置word不可见
        app.setProperty("Visible", new Variant(false));

        //获得documents对象
        Object docs = app.getProperty("Documents").toDispatch();

        //打开第一个文件
        Object doc = Dispatch

            .invoke(
                    (Dispatch) docs,

                    "Open",
                    Dispatch.Method,

                    new Object[] { (String) fileList.get(0),
                            new Variant(false), new Variant(true) },

                    new int[3]).toDispatch();
        //追加文件

        for (int i = 1; i < fileList.size(); i++) {
            Dispatch.invoke(app.getProperty("Selection").toDispatch(),

                "insertFile", Dispatch.Method, new Object[] {
                        (String) fileList.get(i), "",

                        new Variant(false), new Variant(false),
                        new Variant(false) }, new int[3]);

        }
        //保存新的word文件

        Dispatch.invoke((Dispatch) doc, "SaveAs", Dispatch.Method,
            new Object[] { savepaths, new Variant(1) }, new int[3]);

        Variant f = new Variant(false);
        Dispatch.call((Dispatch) doc, "Close", f);

    } catch (Exception e) {
        throw new RuntimeException("合并word文件出错.原因:" + e);

    } finally {
        app.invoke("Quit", new Variant[] {});

    }
}

使用 J

Posted on

使用 J-Interop 在 Java 中调用WMI

我的空间 |邀请 |登录|注册 简单就是最好的,java web 开发,simple 让你化繁为简 !

首页新闻资讯博客论坛Simple市场全面介绍simple3演示simple4演示My Portal

SimpleFramework开发者必读

赵老师的博客

关注 (1)

博客»赵老师»显示全文

使用 J-Interop 在 Java 中调用WMI 5评/3355阅

发表于: 2011-06-16 07:12

有关**WMI**的小知识

Windows**管理规范(WMI)**.aspx)是微软对来自分布式管理任务组DMTF)的基于Web的企业管理(WBEM)和通用信息模型 "Common Information Model (computing)")(CIM)标准的实现。WMI用于访问Windows系统、应用、网络、设备等组件,并管理它们。连接到一台机器通过DCOM进行管理。因此,有关DCOM的小知识将有助于本文的理解。你可以到MSDN了解有关WMI的更多细节。

J-Interop

市场上有一些在使用 JAVA 调用 WMI 的好库,包括 J-InteropJACOB-ProjectJ-Integra。其中,我更喜欢J-Interop,因为它是完全免费和开源的API。它提供了没有任何依赖的纯DCOM桥,完全用Java编写的没有任何JNI代码。

使用**WMI管理Windows**服务

现在,来看一个使用JAVA调用WMI的例子。这个例子利用J-Interop的API使用Win32_Service类解释WMI操作,将启动和停止在这个例子中的窗口服务。

步骤**1:连接到WBEM**服务

下面的代码示例显示了使用J-Interop如何初始化DCOM会话,并连接到远程DCOM服务使。它使用SWbemLocator对象连接到SWbemServicesSWbemServices对象提供对本地或远程计算机WMI的访问,它调用“ConnectServer”方法连接到SWbemServices**。在本例中,提供管理员级别的用户连接到远程计算机。** JISessiondcomSession=JISession.createSession(domainName,userName,password); dcomSession.useSessionSecurity(false); JIComServercomServer=newJIComServer(valueOf("WbemScripting.SWbemLocator"),hostIP,dcomSession); IJIDispatchwbemLocator=(IJIDispatch)narrowObject(comServer.createInstance().queryInterface(IID)); //parameterstoconnecttoWbemScripting.SWbemLocator Object[]params=newObject[]{ newJIString(hostIP),//strServer newJIString(win32_namespace),//strNamespace JIVariant.OPTIONAL_PARAM(),//strUser JIVariant.OPTIONAL_PARAM(),//strPassword JIVariant.OPTIONAL_PARAM(),//strLocale JIVariant.OPTIONAL_PARAM(),//strAuthority newInteger(0),//iSecurityFlags JIVariant.OPTIONAL_PARAM()//objwbemNamedValueSet }; JIVariantresults[]=wbemLocator.callMethodA("ConnectServer",params); IJIDispatchwbemServices=(IJIDispatch)narrowObject(results[0].getObjectAsComObject());

domainName=远程计算机域名,hostIP=远程计算机IP地址,用户名=管理员级别的用户,密码=密码)

第**2步:获取Win32_Service**实例

一旦你获得对SWbemServices对象的引用,就可以调用这个类的任何方法。其中WbemServices.InstancesOf**方法获得任何Win32类的实例。**

也可以使用WMI查询语言(WQL)达到同样的目的,如下所示: finalintRETURN_IMMEDIATE=0x10; finalintFORWARD_ONLY=0x20; Object[]params=newObject[]{ newJIString("SELECT/*FROMWin32_Service"), JIVariant.OPTIONAL_PARAM(), newJIVariant(newInteger(RETURN_IMMEDIATE+FORWARD_ONLY)) }; JIVariant[]servicesSet=wbemServices.callMethodA("ExecQuery",params); IJIDispatchwbemObjectSet=(IJIDispatch)narrowObject(servicesSet[0].getObjectAsComObject());

第三步:执行方法

现在,已得到Win32_Service类的实例,可采用下述代码来调用同一类的方法,因为,它返回多个服务实例,要列举它们以便获取IJIDispatcher服务。 JIVariant newEnumvariant = wbemObjectSet.get("_NewEnum"); IJIComObject enumComObject = newEnumvariant.getObjectAsComObject(); IJIEnumVariant enumVariant = (IJIEnumVariant) narrowObject(enumComObject.queryInterface(IJIEnumVariant.IID)); Object[] elements = enumVariant.next(1); JIArray aJIArray = (JIArray) elements[0]; JIVariant[] array = (JIVariant[]) aJIArray.getArrayInstance(); for (JIVariant variant : array) { IJIDispatch wbemObjectDispatch = (IJIDispatch) narrowObject(variant.getObjectAsComObject()); JIVariant returnStatus = wbemObjectDispatch.callMethodA("StopService"); System.out.println(returnStatus.getObjectAsInt()); }

现在,下面的代码显示了一个使用WMI启动和停止Windows服务的完整Java类。

packagecom.wmi.windows; importstaticorg.jinterop.dcom.core.JIProgId.valueOf; importstaticorg.jinterop.dcom.impls.JIObjectFactory.narrowObject; importstaticorg.jinterop.dcom.impls.automation.IJIDispatch.IID; importjava.util.logging.Level; importorg.jinterop.dcom.common.JIException; importorg.jinterop.dcom.common.JIRuntimeException; importorg.jinterop.dcom.common.JISystem; importorg.jinterop.dcom.core.IJIComObject; importorg.jinterop.dcom.core.JIArray; importorg.jinterop.dcom.core.JIComServer; importorg.jinterop.dcom.core.JISession; importorg.jinterop.dcom.core.JIString; importorg.jinterop.dcom.core.JIVariant; importorg.jinterop.dcom.impls.automation.IJIDispatch; importorg.jinterop.dcom.impls.automation.IJIEnumVariant; publicclassServiceManager{ privatestaticStringdomainName=""; privatestaticStringuserName="administrator"; privatestaticStringpassword=""; privatestaticStringhostIP="127.0.0.1"; privatestaticfinalStringwin32namespace="ROOT\CIMV2"; privatestaticfinalintSTOP_SERVICE=0; privatestaticfinalintSTART_SERVICE=1; privateJISessiondcomSession=null; /// / /@paramargs // publicstaticvoidmain(String[]args){ ServiceManagermanager=newServiceManager(); manager.stopService(domainName,hostIP,userName,password,"MySql");//stopsaservicenamedMySql } /// /Startsagivenserviceifitsstopped. / /@paramdomainName /@paramhostname /@paramusername /@parampassword /@paramserviceName // publicvoidstartService(StringdomainName,Stringhostname,Stringusername,Stringpassword,StringserviceName){ execute(domainName,hostname,username,password,serviceName,START_SERVICE); } /// /Stopsagivenserviceifitsrunning. / /@paramdomainName /@paramhostname /@paramusername /@parampassword /@paramserviceName // publicvoidstopService(StringdomainName,Stringhostname,Stringusername,Stringpassword,StringserviceName){ execute(domainName,hostname,username,password,serviceName,STOP_SERVICE); } /// /Starts/Stopsagivenserviceofremotemachineashostname. / /@paramdomainName /@paramhostname /@paramusername /@parampassword /@paramserviceName /@paramaction // publicvoidexecute(StringdomainName,Stringhostname,Stringusername,Stringpassword,StringserviceName,intaction){ try{ IJIDispatchwbemServices=createCOMServer(); finalintRETURN_IMMEDIATE=0x10; finalintFORWARD_ONLY=0x20; Object[]params=newObject[]{ newJIString("SELECT/*FROMWin32_ServiceWHEREName='"+serviceName+"'"), JIVariant.OPTIONAL_PARAM(), newJIVariant(newInteger(RETURN_IMMEDIATE+FORWARD_ONLY)) }; JIVariant[]servicesSet=wbemServices.callMethodA("ExecQuery",params); IJIDispatchwbemObjectSet=(IJIDispatch)narrowObject(servicesSet[0].getObjectAsComObject()); JIVariantnewEnumvariant=wbemObjectSet.get("_NewEnum"); IJIComObjectenumComObject=newEnumvariant.getObjectAsComObject(); IJIEnumVariantenumVariant=(IJIEnumVariant)narrowObject(enumComObject.queryInterface(IJIEnumVariant.IID)); Object[]elements=enumVariant.next(1); JIArrayaJIArray=(JIArray)elements[0]; JIVariant[]array=(JIVariant[])aJIArray.getArrayInstance(); for(JIVariantvariant:array){ IJIDispatchwbemObjectDispatch=(IJIDispatch)narrowObject(variant.getObjectAsComObject()); //Printobjectastext. JIVariant[]v=wbemObjectDispatch.callMethodA("GetObjectText",newObject[]{1}); System.out.println(v[0].getObjectAsString().getString()); //StartorStoptheservice StringmethodToInvoke=(action==START_SERVICE)?"StartService":"StopService"; JIVariantreturnStatus=wbemObjectDispatch.callMethodA(methodToInvoke); System.out.println("Returnstatus:"+returnStatus.getObjectAsInt());//ifreturncode=0success.Seemsdnformoredetailsaboutthemethod. } }catch(Exceptione){ e.printStackTrace(); }finally{ if(dcomSession!=null){ try{ JISession.destroySession(dcomSession); }catch(Exceptionex){ ex.printStackTrace(); } } } } /// /InitializeDCOMsessionandconnecttoSWBEMserviceongivenhostmachine. /@return /*/ privateIJIDispatchcreateCOMServer(){ JIComServercomServer; try{ JISystem.getLogger().setLevel(Level.WARNING); JISystem.setAutoRegisteration(true); dcomSession=JISession.createSession(domainName,userName,password); dcomSession.useSessionSecurity(false); comServer=newJIComServer(valueOf("WbemScripting.SWbemLocator"),hostIP,dcomSession); IJIDispatchwbemLocator=(IJIDispatch)narrowObject(comServer.createInstance().queryInterface(IID)); //parameterstoconnecttoWbemScripting.SWbemLocator Object[]params=newObject[]{ newJIString(hostIP),//strServer newJIString(win32_namespace),//strNamespace JIVariant.OPTIONAL_PARAM(),//strUser JIVariant.OPTIONAL_PARAM(),//strPassword JIVariant.OPTIONAL_PARAM(),//strLocale JIVariant.OPTIONAL_PARAM(),//strAuthority newInteger(0),//iSecurityFlags JIVariant.OPTIONAL_PARAM()//objwbemNamedValueSet }; JIVariantresults[]=wbemLocator.callMethodA("ConnectServer",params); IJIDispatchwbemServices=(IJIDispatch)narrowObject(results[0].getObjectAsComObject()); returnwbemServices; }catch(JIExceptionjie){ System.out.println(jie.getMessage()); jie.printStackTrace(); }catch(JIRuntimeExceptionjire){ jire.printStackTrace(); }catch(Exceptione){ e.printStackTrace(); }finally{ if(dcomSession!=null){ try{ JISession.destroySession(dcomSession); }catch(JIExceptione){ e.printStackTrace(); } } } returnnull; } }

【原文】http://nikunjp.wordpress.com/ 评论 (共 5 条评论)

匿名 (219.142.23.106), 475天前

j-interop 远程收集WIN7 的eventlog日志怎么不行啊,求助赵老师 回复|支持|反对 匿名 (219.142.23.106), 475天前

是啊,win7怎么不行呢。。 回复|支持|反对

匿名 (59.40.119.215), 497天前

xp的开始Remote Register 服务就可以了。 win7还在研究中 回复|支持|反对 匿名 (219.133.0.1), 501天前

win7平台为什么会用不了呢? 我也测试过了,xp的机器可以成功运行。 有些xp的也不行,我觉得可能是有什么配置项没有配置而导致。 回复|支持|反对

匿名 (111.4.219.247), 722天前

我测试报错:The system cannot find the file specified. win7平台。 回复|支持|反对 (共5, 显示全部)/

表情 发表评论

看不清楚,再换一张 高级模式

相关主题

JAVA问题定位技术 2/3333

sword, 799天前

Java序列化和克隆 0/1568

书生, 870天前 Java EE6中的装饰器,高级用法 0/1163

赵老师, 733天前

通过 Java 编程处理 XML 服务定义 1/1691

书生, 877天前 解析Java软件开发中的五种认识误区 0/1178

书生, 792天前

Java内省和反射机制三步曲之(2)反射 0/1409

书生, 854天前

一周点击排行 留言|联系我们|版权声明|关于

simpleframework.net Copyright ©2011 版权所有

Powered by SimpleFramework [ 0.156 s ]

*

  • 数据装载中... *

聊聊并发(五)——原子操作的实现原理

Posted on

聊聊并发(五)——原子操作的实现原理

分享到

百度分享

聊聊并发(五)——原子操作的实现原理

作者 方腾飞 发布于 十一月 29, 2012 | 14 评论

1. 引言

原子(atom)本意是“不能被进一步分割的最小粒子”,而原子操作(atomic operation)意为"不可被中断的一个或一系列操作" 。在多处理器上实现原子操作就变得有点复杂。本文让我们一起来聊一聊在Intel处理器和Java里是如何实现原子操作的。

2. 术语定义

术语 英文 解释 缓存行 Cache line 缓存的最小操作单位 比较并交换 Compare and Swap CAS操作需要输入两个数值,一个旧值(期望操作前的值)和一个新值,在操作期间先比较下旧值有没有发生变化,如果没有发生变化,才交换成新值,发生了变化则不交换。 CPU流水线 CPU pipeline CPU流水线的工作方式就象工业生产上的装配流水线,在CPU中由5~6个不同功能的电路单元组成一条指令处理流水线,然后将一条X86指令分成5~6步后再由这些电路单元分别执行,这样就能实现在一个CPU时钟周期完成一条指令,因此提高CPU的运算速度。 内存顺序冲突 Memory order violation 内存顺序冲突一般是由假共享引起,假共享是指多个CPU同时修改同一个缓存行的不同部分而引起其中一个CPU的操作无效,当出现这个内存顺序冲突时,CPU必须清空流水线。

3. 处理器如何实现原子操作

32位IA-32处理器使用基于对缓存加锁或总线加锁的方式来实现多处理器之间的原子操作。

3.1 处理器自动保证基本内存操作的原子性

首先处理器会自动保证基本的内存操作的原子性。处理器保证从系统内存当中读取或者写入一个字节是原子的,意思是当一个处理器读取一个字节时,其他处理器不能访问这个字节的内存地址。奔腾6和最新的处理器能自动保证单处理器对同一个缓存行里进行16/32/64位的操作是原子的,但是复杂的内存操作处理器不能自动保证其原子性,比如跨总线宽度,跨多个缓存行,跨页表的访问。但是处理器提供总线锁定和缓存锁定两个机制来保证复杂内存操作的原子性。

3.2 使用总线锁保证原子性

第一个机制是通过总线锁保证原子性。如果多个处理器同时对共享变量进行读改写(i++就是经典的读改写操作)操作,那么共享变量就会被多个处理器同时进行操作,这样读改写操作就不是原子的,操作完之后共享变量的值会和期望的不一致,举个例子:如果i=1,我们进行两次i++操作,我们期望的结果是3,但是有可能结果是2。如下图

(例1)

原因是有可能多个处理器同时从各自的缓存中读取变量i,分别进行加一操作,然后分别写入系统内存当中。那么想要保证读改写共享变量的操作是原子的,就必须保证CPU1读改写共享变量的时候,CPU2不能操作缓存了该共享变量内存地址的缓存。

处理器使用总线锁就是来解决这个问题的。所谓总线锁就是使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住,那么该处理器可以独占使用共享内存。

3.3 使用缓存锁保证原子性

第二个机制是通过缓存锁定保证原子性。在同一时刻我们只需保证对某个内存地址的操作是原子性即可,但总线锁定把CPU和内存之间通信锁住了,这使得锁定期间,其他处理器不能操作其他内存地址的数据,所以总线锁定的开销比较大,最近的处理器在某些场合下使用缓存锁定代替总线锁定来进行优化。

频繁使用的内存会缓存在处理器的L1,L2和L3高速缓存里,那么原子操作就可以直接在处理器内部缓存中进行,并不需要声明总线锁,在奔腾6和最近的处理器中可以使用“缓存锁定”的方式来实现复杂的原子性。所谓“缓存锁定”就是如果缓存在处理器缓存行中内存区域在LOCK操作期间被锁定,当它执行锁操作回写内存时,处理器不在总线上声言LOCK#信号,而是修改内部的内存地址,并允许它的缓存一致性机制来保证操作的原子性,因为缓存一致性机制会阻止同时修改被两个以上处理器缓存的内存区域数据,当其他处理器回写已被锁定的缓存行的数据时会起缓存行无效,在例1中,当CPU1修改缓存行中的i时使用缓存锁定,那么CPU2就不能同时缓存了i的缓存行。

但是有两种情况下处理器不会使用缓存锁定。第一种情况是:当操作的数据不能被缓存在处理器内部,或操作的数据跨多个缓存行(cache line),则处理器会调用总线锁定。第二种情况是:有些处理器不支持缓存锁定。对于Inter486和奔腾处理器,就算锁定的内存区域在处理器的缓存行中也会调用总线锁定。

以上两个机制我们可以通过Inter处理器提供了很多LOCK前缀的指令来实现。比如位测试和修改指令BTS,BTR,BTC,交换指令XADD,CMPXCHG和其他一些操作数和逻辑指令,比如ADD(加),OR(或)等,被这些指令操作的内存区域就会加锁,导致其他处理器不能同时访问它。

4. JAVA如何实现原子操作

在java中可以通过锁和循环CAS的方式来实现原子操作。

4.1 使用循环CAS实现原子操作

JVM中的CAS操作正是利用了上一节中提到的处理器提供的CMPXCHG指令实现的。自旋CAS实现的基本思路就是循环进行CAS操作直到成功为止,以下代码实现了一个基于CAS线程安全的计数器方法safeCount和一个非线程安全的计数器count。 public class Counter { private AtomicInteger atomicI = new AtomicInteger(0); private int i = 0; public static void main(String[] args) { final Counter cas = new Counter(); List ts = new ArrayList(600); long start = System.currentTimeMillis(); for (int j = 0; j < 100; j++) { Thread t = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10000; i++) { cas.count(); cas.safeCount(); } } }); ts.add(t); } for (Thread t : ts) { t.start(); } // 等待所有线程执行完成 for (Thread t : ts) { try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(cas.i); System.out.println(cas.atomicI.get()); System.out.println(System.currentTimeMillis() - start); } /// / 使用CAS实现线程安全计数器 // private void safeCount() { for (;;) { int i = atomicI.get(); boolean suc = atomicI.compareAndSet(i, ++i); if (suc) { break; } } } /// / 非线程安全计数器 // private void count() { i++; } }

在java并发包中有一些并发框架也使用了自旋CAS的方式来实现原子操作,比如LinkedTransferQueue类的Xfer方法。CAS虽然很高效的解决原子操作,但是CAS仍然存在三大问题。ABA问题,循环时间长开销大和只能保证一个共享变量的原子操作。

  1. ABA问题。因为CAS需要在操作值的时候检查下值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。ABA问题的解决思路就是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加一,那么A-B-A 就会变成1A-2B-3A。 从Java1.5开始JDK的atomic包里提供了一个类AtomicStampedReference来解决ABA问题。这个类的compareAndSet方法作用是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。 public boolean compareAndSet (V expectedReference,//预期引用 V newReference,//更新后的引用 int expectedStamp, //预期标志 int newStamp) //更新后的标志
  2. 循环时间长开销大。自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销。如果JVM能支持处理器提供的pause指令那么效率会有一定的提升,pause指令有两个作用,第一它可以延迟流水线执行指令(de-pipeline),使CPU不会消耗过多的执行资源,延迟的时间取决于具体实现的版本,在一些处理器上延迟时间是零。第二它可以避免在退出循环的时候因内存顺序冲突(memory order violation)而引起CPU流水线被清空(CPU pipeline flush),从而提高CPU的执行效率。
  3. 只能保证一个共享变量的原子操作。当对一个共享变量执行操作时,我们可以使用循环CAS的方式来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候就可以用锁,或者有一个取巧的办法,就是把多个共享变量合并成一个共享变量来操作。比如有两个共享变量i=2,j=a,合并一下ij=2a,然后用CAS来操作ij。从Java1.5开始JDK提供了AtomicReference类来保证引用对象之间的原子性,你可以把多个变量放在一个对象里来进行CAS操作。

4.2 使用锁机制实现原子操作

锁机制保证了只有获得锁的线程能够操作锁定的内存区域。JVM内部实现了很多种锁机制,有偏向锁,轻量级锁和互斥锁,有意思的是除了偏向锁,JVM实现锁的方式都用到的循环CAS,当一个线程想进入同步块的时候使用循环CAS的方式来获取锁,当它退出同步块的时候使用循环CAS释放锁。详细说明可以参见文章Java SE1.6中的Synchronized。

5. 参考资料

  1. Java SE1.6中的Synchronized
  2. Intel 64和IA-32架构软件开发人员手册
  3. 深入分析Volatile的实现原理

作者介绍

方腾飞,花名清英,淘宝资深开发工程师,关注并发编程,目前在广告技术部从事无线广告联盟的开发和设计工作。个人博客:http://ifeve.com 微博:http://weibo.com/kirals 欢迎通过我的微博进行技术交流。

感谢张龙对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。

相关内容

您好,陌生人!

您需要 注册一个InfoQ账号 或者 登录 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

社区评论 Watch Thread

您好,有个地方不太明白 by 王 凯 Posted 30/11/2012 05:01 Re: 您好,有个地方不太明白 by 方 腾飞 Posted 30/11/2012 05:14

Re: 您好,有个地方不太明白 by 王 凯 Posted 30/11/2012 05:21 期待看到happens-before的深入解读 by freish freish Posted 05/12/2012 08:54

Re: 期待看到happens-before的深入解读 by 方 腾飞 Posted 05/12/2012 11:04 缓存锁定一处不太明白 by 陈 良柱 Posted 18/12/2012 08:20

Re: 缓存锁定一处不太明白 by 方 腾飞 Posted 27/12/2012 01:00 Re: 缓存锁定一处不太明白 by Zhao Yu Posted 27/12/2012 10:20

Re: 缓存锁定一处不太明白 by 方 腾飞 Posted 31/12/2012 10:28 Re: 缓存锁定一处不太明白 by 陈 良柱 Posted 31/12/2012 09:29

缓存锁定 by Zhao Yu Posted 25/12/2012 04:19 Re: 缓存锁定 by 方 腾飞 Posted 27/12/2012 00:59

关于总线锁的问题 by lee jw Posted 29/12/2012 12:54 Re: 关于总线锁的问题 by 方 腾飞 Posted 31/12/2012 10:30

您好,有个地方不太明白 30/11/2012 05:01 by 王 凯

safeCount()方法有些看不明白,直接让atomicI自增不可以吗,AtomicInteger本身不就是原子方式增加的吗,谢谢。

Re: 您好,有个地方不太明白 30/11/2012 05:14 by 方 腾飞

atomicI.compareAndSet(i, ++i);本身是原子方式的增加,但是有可能会增加失败,所以需要不停atomicI.compareAndSet(i, ++i);

Re: 您好,有个地方不太明白 30/11/2012 05:21 by 王 凯

哦,明白了,我看了下AtomicInteger的源码,incrementAndGet方法实现,呵呵

期待看到happens-before的深入解读 05/12/2012 08:54 by freish freish

期待看到happens-before的深入解读

Re: 期待看到happens-before的深入解读 05/12/2012 11:04 by 方 腾飞

好的,没问题,在JMM文章里我会深入解读下。

缓存锁定一处不太明白 18/12/2012 08:20 by 陈 良柱

缓存失效是在内存写回之前还是之后?如何使得其他cpu的缓存失效?是说内存到缓存的映射是一共享区域且回写内存包含对其的检查吗?

缓存锁定 25/12/2012 04:19 by Zhao Yu

“所谓“缓存锁定”就是如果缓存在处理器缓存行中内存区域在LOCK操作期间被锁定,当它执行锁操作回写内存时,处理器不在总线上声言LOCK#信号,而是修改内部的内存地址,并允许它的缓存一致性机制来保证操作的原子性” 这句实在不理解,首先什么是Lock操作期间?不是不锁总线了嘛?为什么还Lock?其次,处理器不发Lock信号而是修改内部的内存地址,到底是怎么保障在一个处理器修改缓存并回写期间,其它处理器不会执行同样操作???望作者解答一下

Re: 缓存锁定 27/12/2012 00:59 by 方 腾飞

Lock操作期间,是指Lock指令执行期间,不锁总线但是锁缓存。 最后一个问题,这个是由缓存一致性协议保证的,详细参见:www.tektalk.org/2011/07/07/cache一致性与2种基本写策略1/

Re: 缓存锁定一处不太明白 27/12/2012 01:00 by 方 腾飞

参见缓存一致性协议:www.tektalk.org/2011/07/07/cache一致性与2种基本写策略1/

Re: 缓存锁定一处不太明白 27/12/2012 10:20 by Zhao Yu

好的~多谢作者的答复,这块内容关注很久了,多线程并发开发程序,那门语言和平台都是学到最后的最为重要,也是最深的地方,希望您继续发表相关博文~

关于总线锁的问题 29/12/2012 12:54 by lee jw

您好,我想请问CPU在什么情况下会发出LOCK/#信号,是在冲突的时候发出,还是在读写内存的时候发出?看您的文章是说CPU1发出LOCK/#信号后,CPU2就不能读写内存,我想请问一下这里面是否有优先级的判断?谢谢

Re: 缓存锁定一处不太明白 31/12/2012 10:28 by 方 腾飞

多谢你的关注,定期会发表新文章的。或者你也可以关注我的小站ifeve.com 最近我在做国外并发编程文章的翻译,都是非常值得一看的文章,你也可以参与到我们的翻译当中来,一起促进并发编程的研究和推广 。

Re: 关于总线锁的问题 31/12/2012 10:30 by 方 腾飞

指令触发的,比如使用lock前缀的指令。

Re: 缓存锁定一处不太明白 31/12/2012 09:29 by 陈 良柱

你给的文章链接没有回答我的问题,不过write-invalidate和write-update两词很有用处。 找到一篇个人认为写得较为清楚的综述文章,在此分享:www.docin.com/p-92508695.html。

关闭

**by

发布于

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p 当有人回复此评论时请E-mail通知我

关闭 主题 您的回复

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p 当有人回复此评论时请E-mail通知我 关闭

深度内容

Juergen Fesslmeier 七月 02, 2013

设计模式自动化

Gael Fraiteur and Yan Cui 七月 01, 2013

设计指尖上的世界:移动用户界面一瞥

Forrest Shull 六月 28, 2013

成功的根本—集成的ALM工具

Dave West 六月 28, 2013

书评:验收测试驱动开发实践指南

Manuel Pais 六月 26, 2013

跨终端的web

舒文亮 六月 26, 2013

语言 & 开发

Juergen Fesslmeier谈端到端的JavaScript开发

MobileCloud for TFS支持测试Windows Phone,Android,iOS及BlackBerry应用

百度技术沙龙第39期回顾:前端快速开发实践(含资料下载)

架构 & 设计

内存与本机代码的性能

设计模式自动化

连接设备编程 过程 & 实践

成功的根本—集成的ALM工具

ThoughtWorks全球CEO郭晓谈软件人才的招聘与培养

书评:验收测试驱动开发实践指南

运维 & 基础架构

在传统企业中引入DevOps

安全性——“DevOpS”中的S

书评:验收测试驱动开发实践指南 企业架构

设计指尖上的世界:移动用户界面一瞥

Stratos 2.0已发布,支持所有运行时环境和30个IaaS

让1.5亿移动端用户第一时间获取消息 Close E-mail 密码

使用Google账号登录 使用Microsoft账号登录 忘记密码? InfoQ账号使用的E-mail 发送邮件

重新登录 重新发送激活信息 重新发送

重新登录 没有用户名?

点击注册

100

Posted on

100%纯java调用windows的wmi获取监控数据 - 肖国颖的个人页面 - 开源中国社区

开源中国社区

开源项目发现、使用和交流平台

当前访客身份: arctichia [ 我的空间 | 退出 ] 你有0新留言

软件 代码 讨论区 新闻 博客

软件

关注(4) 粉丝(71) 积分(280)

不做鬼中鬼,怎做人上人 .发送留言 .请教问题

博客分类

  1. 1. 在Android中嵌入AdMob广告,赚午饭钱
  2. 2. 解决iOS6看YouTb的心酸,补充可看版(goagent+opendoor)
  3. 3. 当单例(Singleton)爱上多线程——重复初始化问题
  4. 4. Java序列化与JSON序列化大比拼
  5. 5. 在Eclipse中用Scala语言开发Android应用
  6. 6. Ubuntu 12.10下用Empathy(pidgin-lwqq)登录QQ
  7. 7. 解决Ubuntu 12.04下频繁死机-Chrome
  8. 8. 以Jar形式为Web项目提供资源文件(JS、CSS与图片)

最新评论

空间 » 博客 » 工作日志 » 博客正文

100%纯java调用windows的wmi获取监控数据

23人收藏此文章, 我要收藏 发表于12个月前(2012-08-16 18:17) , 已有2348次阅读 ,共5个评论

纯java主要体现在可以跨平台调用com。所用的是j-Interop,它是100%纯java实现的com的调用

1、环境准备

a、windows要开启Remote Registry与Windows Management Instrumentation服务

b、修改安全策略

我系统是英文的,如果是中文系统,翻译为中文,相对应的查找并修改。

Administrative Tools>Local Security Policy>Local Policy>Security Policy>Network access: Sharing and security model for local accounts

修改为Classic(经典)

c、禁用放火墙

d、window2008系统注册表越狱(高版本的win)

需要修改regedit中HKEY_CLASSES_ROOT\CLSID{76A64158-CB41-11D1-8B02-00600806D9B6}的权限,windows2008不再给Administrators完全控制权。

下载SetACL.exe,下载地址:http://files.helgeklein.com/downloads/SetACL/current/SetACL%20(executable%20version).zip

set_wmi_reg_acl.cmd

view sourceprint?

1

SetACL.exe -on

"HKEY_CLASSES_ROOT\CLSID{76A64158-CB41-11D1-8B02-00600806D9B6}"

-ot reg -actn setowner -ownr

"n:Administrators"

2

SetACL.exe -on

"HKEY_CLASSES_ROOT\CLSID{76A64158-CB41-11D1-8B02-00600806D9B6}"

-ot reg -actn ace -ace

"n:Administrators;p:full"

以超级管理员身份执行这个cms,就会把owner与完全控制权限授予Administrators组

#

2、程序代码

java类

view sourceprint?

001

package

org.noah.wmitest;

002

003

import

org.jinterop.dcom.common.JIException;

004

import

org.jinterop.dcom.common.JISystem; 005

import

org.jinterop.dcom.core./*;

006

import

org.jinterop.dcom.impls.JIObjectFactory; 007

import

org.jinterop.dcom.impls.automation.IJIDispatch;

008

import

org.jinterop.dcom.impls.automation.IJIEnumVariant; 009

import

org.slf4j.Logger;

010

import

org.slf4j.LoggerFactory; 011

012

import

java.net.UnknownHostException; 013

import

java.util.logging.Level;

014

015

///

016

/* Created with IntelliJ IDEA. 017

/* User: noah

018

/* Date: 8/16/12 019

/* Time: 8:00 AM

020

/* To change this template use File | Settings | File Templates. 021

/*/

022

public

class

WmiService { 023

024

private

JIComServer m_ComStub =

null

; 025

private

IJIComObject m_ComObject =

null

;

026

private

IJIDispatch m_Dispatch =

null

; 027

private

String m_Address =

null

;

028

private

JISession m_Session =

null

; 029

private

IJIDispatch m_WbemServices =

null

;

030

031

private

static

final

String WMI_CLSID =

"76A6415B-CB41-11d1-8B02-00600806D9B6"

;

032

private

static

final

String WMI_PROGID =

"WbemScripting.SWbemLocator"

; 033

034

private

Logger logger = LoggerFactory.getLogger(

this

.getClass()); 035

036

037

public

WmiService(String address) {

038

JISystem.setAutoRegisteration(

true

); 039

JISystem.getLogger().setLevel(Level.WARNING);

040

m_Address = address; 041

}

042

043

public

void

query(String strQuery) {

044

045

System.out.println(

"query:"

  • strQuery);

046

047

JIVariant results[] =

new

JIVariant[

0

];

048

try

{ 049

results = m_WbemServices.callMethodA(

"ExecQuery"

,

new

Object[]{

new

JIString(strQuery), JIVariant.OPTIONAL_PARAM(), JIVariant.OPTIONAL_PARAM(), JIVariant.OPTIONAL_PARAM()});

050

IJIDispatch wOSd = (IJIDispatch) JIObjectFactory.narrowObject((results[

0

]).getObjectAsComObject()); 051

052

int

count = wOSd.get(

"Count"

).getObjectAsInt(); 053

054

IJIComObject enumComObject = wOSd.get(

"_NewEnum"

).getObjectAsComObject(); 055

IJIEnumVariant enumVariant = (IJIEnumVariant) JIObjectFactory.narrowObject(enumComObject.queryInterface(IJIEnumVariant.IID));

056

057

IJIDispatch wbemObject_dispatch =

null

;

058

059

for

(

int

c =

0

; c < count; c++) {

060

061

Object[] values = enumVariant.next(

1

);

062

JIArray array = (JIArray) values[

0

]; 063

Object[] arrayObj = (Object[]) array.getArrayInstance();

064

for

(

int

j =

0

; j < arrayObj.length; j++) { 065

wbemObject_dispatch = (IJIDispatch) JIObjectFactory.narrowObject(((JIVariant) arrayObj[j]).getObjectAsComObject());

066

} 067

068

String str = (wbemObject_dispatch.callMethodA(

"GetObjectText_"

,

new

Object[]{

1

}))[

0

].getObjectAsString2(); 069

System.out.println(

"("

  • c +

"):"

);

070

System.out.println(str); 071

System.out.println();

072

} 073

074

075

}

catch

(JIException e) {

076

e.printStackTrace(); 077

}

078

} 079

080

public

void

connect(

final

String domain,

final

String username,

final

String password) { 081

try

{

082

083

m_Session = JISession.createSession(domain, username, password);

084

m_Session.useSessionSecurity(

true

); 085

m_Session.setGlobalSocketTimeout(

5000

);

086

087

m_ComStub =

new

JIComServer(JIProgId.valueOf(WMI_PROGID), m_Address, m_Session);

088

089

IJIComObject unknown = m_ComStub.createInstance();

090

m_ComObject = unknown.queryInterface(WMI_CLSID); 091

092

m_Dispatch = (IJIDispatch) JIObjectFactory.narrowObject(m_ComObject.queryInterface(IJIDispatch.IID)); 093

JIVariant results[] = m_Dispatch.callMethodA(

094

"ConnectServer"

, 095

new

Object[]{

096

new

JIString(m_Address), 097

JIVariant.OPTIONAL_PARAM(),

098

JIVariant.OPTIONAL_PARAM(), 099

JIVariant.OPTIONAL_PARAM(),

100

JIVariant.OPTIONAL_PARAM(), 101

JIVariant.OPTIONAL_PARAM(),

102

0

, 103

JIVariant.OPTIONAL_PARAM()

104

} 105

);

106

107

m_WbemServices = (IJIDispatch) JIObjectFactory.narrowObject((results[

0

]).getObjectAsComObject());

108

109

}

catch

(JIException e) {

110

e.printStackTrace(); 111

if

(m_Session !=

null

) {

112

try

{ 113

JISession.destroySession(m_Session);

114

}

catch

(JIException e1) { 115

logger.error(e.getMessage(), e);

116

} 117

}

118

}

catch

(UnknownHostException e) { 119

if

(m_Session !=

null

) {

120

try

{ 121

JISession.destroySession(m_Session);

122

}

catch

(JIException e1) { 123

logger.error(e.getMessage(), e);

124

} 125

}

126

} 127

}

128

129

public

void

disconnect() {

130

try

{ 131

JISession.destroySession(m_Session);

132

}

catch

(JIException e) { 133

logger.error(e.getMessage(), e);

134

} 135

}

136

137

138

public

static

void

main(String[] args) { 139

140

WmiService wmiService =

new

WmiService(

"172.16.158.129"

); 141

142

//域(一般为空字符),用户名,密码 143

wmiService.connect(

""

,

"username"

,

"password"

);

144

145

//系统信息

146

wmiService.query(

"SELECT /* FROM Win32_ComputerSystem"

); 147

148

//CPU信息 149

wmiService.query(

"SELECT /* FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name != '_Total'"

);

150

151

//内存信息

152

wmiService.query(

"SELECT /* FROM Win32_PerfFormattedData_PerfOS_Memory"

); 153

154

//磁盘信息 155

wmiService.query(

"SELECT /* FROM Win32_PerfRawData_PerfDisk_PhysicalDisk Where Name != '_Total'"

);

156

157

wmiService.disconnect();

158

} 159

}

mavne配置(pom.xml) view sourceprint?

01

<?

xml

version

=

"1.0"

encoding

=

"UTF-8"

?>

02

<

project

xmlns

=

"http://maven.apache.org/POM/4.0.0" 03

xmlns:xsi

=

"http://www.w3.org/2001/XMLSchema-instance"

04

xsi:schemaLocation

=

"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"

> 05

<

modelVersion

4.0.0</

modelVersion

>

06

07

<

groupId

org.noahx</

groupId

>

08

<

artifactId

wmi-test</

artifactId

> 09

<

version

1.0</

version

>

10

11

12

<

dependencies

> 13

14

<

dependency

> 15

<

groupId

org.kohsuke.jinterop</

groupId

>

16

<

artifactId

j-interop</

artifactId

> 17

<

version

2.0.8-kohsuke-1</

version

>

18

</

dependency

> 19

20

<

dependency

> 21

<

groupId

org.slf4j</

groupId

>

22

<

artifactId

slf4j-log4j12</

artifactId

> 23

<

version

1.6.4</

version

>

24

</

dependency

> 25

26

</

dependencies

> 27

28

</

project

>

运行结果

view sourceprint?

001

query:SELECT /* FROM Win32_ComputerSystem

002

(0): 003

004

instance of Win32_ComputerSystem 005

{

006

AdminPasswordStatus = 1; 007

AutomaticResetBootOption = FALSE;

008

AutomaticResetCapability = TRUE; 009

BootOptionOnLimit = 3;

010

BootOptionOnWatchDog = 3; 011

BootROMSupported = TRUE;

012

BootupState =

"Normal boot"

; 013

Caption =

"NAK-E1A7C21EA3C"

;

014

ChassisBootupState = 3; 015

CreationClassName =

"Win32_ComputerSystem"

;

016

CurrentTimeZone = 480; 017

Description =

"AT/AT COMPATIBLE"

;

018

Domain =

"WORKGROUP"

; 019

DomainRole = 0;

020

EnableDaylightSavingsTime = TRUE; 021

FrontPanelResetStatus = 3;

022

InfraredSupported = FALSE; 023

KeyboardPasswordStatus = 3;

024

Manufacturer =

"VMware, Inc."

; 025

Model =

"VMware Virtual Platform"

;

026

Name =

"NAK-E1A7C21EA3C"

; 027

NetworkServerModeEnabled = TRUE;

028

NumberOfLogicalProcessors = 2; 029

NumberOfProcessors = 1;

030

OEMStringArray = {

"[MS_VM_CERT/SHA1/27d66596a61c48dd3dc7216fd715126e33f59ae7]"

,

"Welcome to the Virtual Machine"

}; 031

PartOfDomain = FALSE;

032

PauseAfterReset =

"3932100000"

; 033

PowerOnPasswordStatus = 0;

034

PowerState = 0; 035

PowerSupplyState = 3;

036

PrimaryOwnerName =

"nak"

; 037

ResetCapability = 1;

038

ResetCount = -1; 039

ResetLimit = -1;

040

Roles = {

"LM_Workstation"

,

"LM_Server"

,

"NT"

,

"Potential_Browser"

,

"Master_Browser"

}; 041

Status =

"OK"

;

042

SystemStartupDelay = 0; 043

SystemStartupOptions = {

"\"Microsoft Windows XP Professional\" /noexecute=optin /fastdetect"

};

044

SystemStartupSetting = 0; 045

SystemType =

"X86-based PC"

;

046

ThermalState = 3; 047

TotalPhysicalMemory =

"1610063872"

;

048

UserName =

"NAK-E1A7C21EA3C\a"

; 049

WakeUpType = 6;

050

}; 051

052

053

query:SELECT /* FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name !=

'_Total'

054

(0): 055

056

instance of Win32_PerfFormattedData_PerfOS_Processor 057

{

058

C1TransitionsPersec =

"77"

; 059

C2TransitionsPersec =

"0"

;

060

C3TransitionsPersec =

"0"

; 061

DPCRate = 0;

062

DPCsQueuedPersec = 4; 063

InterruptsPersec = 71;

064

Name =

"0"

; 065

PercentC1Time =

"96"

;

066

PercentC2Time =

"0"

; 067

PercentC3Time =

"0"

;

068

PercentDPCTime =

"0"

; 069

PercentIdleTime =

"100"

;

070

PercentInterruptTime =

"0"

; 071

PercentPrivilegedTime =

"0"

;

072

PercentProcessorTime =

"0"

; 073

PercentUserTime =

"0"

;

074

}; 075

076

077

(1):

078

079

instance of Win32_PerfFormattedData_PerfOS_Processor

080

{ 081

C1TransitionsPersec =

"83"

;

082

C2TransitionsPersec =

"0"

; 083

C3TransitionsPersec =

"0"

;

084

DPCRate = 0; 085

DPCsQueuedPersec = 10;

086

InterruptsPersec = 67; 087

Name =

"1"

;

088

PercentC1Time =

"96"

; 089

PercentC2Time =

"0"

;

090

PercentC3Time =

"0"

; 091

PercentDPCTime =

"0"

;

092

PercentIdleTime =

"100"

; 093

PercentInterruptTime =

"0"

;

094

PercentPrivilegedTime =

"0"

; 095

PercentProcessorTime =

"0"

;

096

PercentUserTime =

"0"

; 097

};

098

099

100

query:SELECT /* FROM Win32_PerfFormattedData_PerfOS_Memory 101

(0):

102

103

instance of Win32_PerfFormattedData_PerfOS_Memory

104

{ 105

AvailableBytes =

"1142099968"

;

106

AvailableKBytes =

"1115332"

; 107

AvailableMBytes =

"1089"

;

108

CacheBytes =

"70725632"

; 109

CacheBytesPeak =

"72904704"

;

110

CacheFaultsPersec = 634; 111

CommitLimit =

"3063078912"

;

112

CommittedBytes =

"326488064"

; 113

DemandZeroFaultsPersec = 13965;

114

FreeSystemPageTableEntries = 159743; 115

PageFaultsPersec = 13965;

116

PageReadsPersec = 0; 117

PagesInputPersec = 0;

118

PagesOutputPersec = 0; 119

PagesPersec = 0;

120

PageWritesPersec = 0; 121

PercentCommittedBytesInUse = 10;

122

PoolNonpagedAllocs = 38040; 123

PoolNonpagedBytes =

"7585792"

;

124

PoolPagedAllocs = 57820; 125

PoolPagedBytes =

"29380608"

;

126

PoolPagedResidentBytes =

"28622848"

; 127

SystemCacheResidentBytes =

"40235008"

;

128

SystemCodeResidentBytes =

"1867776"

; 129

SystemCodeTotalBytes =

"1167360"

;

130

SystemDriverResidentBytes =

"0"

; 131

SystemDriverTotalBytes =

"4071424"

;

132

TransitionFaultsPersec = 0; 133

WriteCopiesPersec = 0;

134

}; 135

136

137

query:SELECT /* FROM Win32_PerfRawData_PerfDisk_PhysicalDisk Where Name !=

'_Total'

138

(0): 139

140

instance of Win32_PerfRawData_PerfDisk_PhysicalDisk 141

{

142

AvgDiskBytesPerRead =

"138920448"

; 143

AvgDiskBytesPerRead_Base = 8000;

144

AvgDiskBytesPerTransfer =

"208285696"

; 145

AvgDiskBytesPerTransfer_Base = 13701;

146

AvgDiskBytesPerWrite =

"69365248"

; 147

AvgDiskBytesPerWrite_Base = 5701;

148

AvgDiskQueueLength =

"581460650"

; 149

AvgDiskReadQueueLength =

"405581626"

;

150

AvgDisksecPerRead = 2794786622; 151

AvgDisksecPerRead_Base = 8000;

152

AvgDisksecPerTransfer = 322083534; 153

AvgDisksecPerTransfer_Base = 13701;

154

AvgDisksecPerWrite = 1822264208; 155

AvgDisksecPerWrite_Base = 5701;

156

AvgDiskWriteQueueLength =

"175879024"

; 157

CurrentDiskQueueLength = 0;

158

DiskBytesPersec =

"208285696"

; 159

DiskReadBytesPersec =

"138920448"

;

160

DiskReadsPersec = 8000; 161

DiskTransfersPersec = 13701;

162

DiskWriteBytesPersec =

"69365248"

; 163

DiskWritesPersec = 5701;

164

Frequency_Object =

"0"

; 165

Frequency_PerfTime =

"3034010000"

;

166

Frequency_Sys100NS =

"10000000"

; 167

Name =

"0 C:"

;

168

PercentDiskReadTime =

"405581626"

; 169

PercentDiskReadTime_Base =

"129895856572522792"

;

170

PercentDiskTime =

"581460650"

; 171

PercentDiskTime_Base =

"129895856572522792"

;

172

PercentDiskWriteTime =

"175879024"

; 173

PercentDiskWriteTime_Base =

"129895856572522792"

;

174

PercentIdleTime =

"18446744072967667781"

; 175

PercentIdleTime_Base =

"129895856572522792"

;

176

SplitIOPerSec = 1074; 177

Timestamp_Object =

"0"

;

178

Timestamp_PerfTime =

"3635534093651"

; 179

Timestamp_Sys100NS =

"129895856572522792"

;

180

};<span style=

"font-family:'sans serif, tahoma, verdana, helvetica';font-size:x-small;"

<span style=

"line-height:18.18181800842285px;white-space:normal;"

#

3、有可能出现的问题

报错a

view sourceprint?

01

org.jinterop.dcom.common.JIException: Message not found

for

errorCode:

0xC0000034

02

at org.jinterop.winreg.smb.JIWinRegStub.winreg_OpenHKLM(JIWinRegStub.java:

115

) 03

at org.jinterop.dcom.core.JIProgId.getIdFromWinReg(JIProgId.java:

130

)

04

at org.jinterop.dcom.core.JIProgId.getCorrespondingCLSID(JIProgId.java:

162

) 05

at org.jinterop.dcom.core.JIComServer.(JIComServer.java:

413

)

06

at org.noah.wmitest.WmiService.connect(WmiService.java:

122

) 07

at org.noah.wmitest.WmiService.main(WmiService.java:

177

)

08

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 09

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:

39

)

10

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:

25

) 11

at java.lang.reflect.Method.invoke(Method.java:

597

)

12

at com.intellij.rt.execution.application.AppMain.main(AppMain.java:

120

) 13

Caused by: jcifs.smb.SmbException: The system cannot find the file specified.

14

at jcifs.smb.SmbTransport.checkStatus(SmbTransport.java:

522

) 15

at jcifs.smb.SmbTransport.send(SmbTransport.java:

622

)

16

at jcifs.smb.SmbSession.send(SmbSession.java:

239

) 17

at jcifs.smb.SmbTree.send(SmbTree.java:

109

)

18

at jcifs.smb.SmbFile.send(SmbFile.java:

718

) 19

at jcifs.smb.SmbFile.open0(SmbFile.java:

923

)

20

at jcifs.smb.SmbFile.open(SmbFile.java:

940

) 21

at jcifs.smb.SmbFileOutputStream.(SmbFileOutputStream.java:

142

)

22

at jcifs.smb.TransactNamedPipeOutputStream.(TransactNamedPipeOutputStream.java:

32

) 23

at jcifs.smb.SmbNamedPipe.getNamedPipeOutputStream(SmbNamedPipe.java:

187

)

24

at rpc.ncacn_np.RpcTransport.attach(RpcTransport.java:

92

) 25

at rpc.Stub.attach(Stub.java:

105

)

26

at rpc.Stub.call(Stub.java:

110

) 27

at org.jinterop.winreg.smb.JIWinRegStub.winreg_OpenHKLM(JIWinRegStub.java:

113

)

28

...

10

more

需要开启Remote Registry服务 报错b

view sourceprint?

01

org.jinterop.dcom.common.JIException: Message not found

for

errorCode:

0xC0000001

02

at org.jinterop.winreg.smb.JIWinRegStub.winreg_OpenHKLM(JIWinRegStub.java:

115

) 03

at org.jinterop.dcom.core.JIProgId.getIdFromWinReg(JIProgId.java:

130

)

04

at org.jinterop.dcom.core.JIProgId.getCorrespondingCLSID(JIProgId.java:

162

) 05

at org.jinterop.dcom.core.JIComServer.(JIComServer.java:

413

)

06

at org.noah.wmitest.WmiService.connect(WmiService.java:

87

) 07

at org.noah.wmitest.WmiService.main(WmiService.java:

142

)

08

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 09

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:

39

)

10

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:

25

) 11

at java.lang.reflect.Method.invoke(Method.java:

597

)

12

at com.intellij.rt.execution.application.AppMain.main(AppMain.java:

120

) 13

Caused by: jcifs.smb.SmbException: Connection timeout

14

jcifs.util.transport.TransportException: Connection timeout 15

16

或 17

18

org.jinterop.dcom.common.JIException: Message not found

for

errorCode:

0x8001FFFF 19

at org.jinterop.dcom.core.JIComServer.init(JIComServer.java:

576

)

20

at org.jinterop.dcom.core.JIComServer.initialise(JIComServer.java:

481

) 21

at org.jinterop.dcom.core.JIComServer.(JIComServer.java:

414

)

22

at org.noah.wmitest.WmiService.connect(WmiService.java:

87

) 23

at org.noah.wmitest.WmiService.main(WmiService.java:

142

)

24

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 25

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:

39

)

26

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:

25

) 27

at java.lang.reflect.Method.invoke(Method.java:

597

)

28

at com.intellij.rt.execution.application.AppMain.main(AppMain.java:

120

) 29

Caused by: java.net.ConnectException: Connection timed out

需要禁用放火墙

4、总结

j-Interop纯java跨平台,我就是linux系统。

用j-Interop就可以很方便的调用windows系统com,虽然这里只演示了WMI。 如果关心WMI与监控的话,建议去opennms-wmi看一看,他们有更好api封装(底层也是j-Interop)。 关键字: wmi windows j-interop

声明:OSCHINA 博客文章版权属于作者,受法律保护。未经作者同意不得转载。

开源中国-程序员在线工具:API文档大全(120+) JS在线编辑演示 二维码 更多>> 分享到: 已有 0人顶

共有 5 条网友评论

能通过代码禁止防火墙么?是都要管理员权限?

WMI里应该就有控制防火墙的。这种操作肯定需要管理员权限了。

不知道远程调用行不行呢?请博主明确一下。

引用来自“黄金比”的评论

不知道远程调用行不行呢?请博主明确一下。 你指的是非本机吗?我测试的方式就是一台linux运行程序指定ip调用另一台win服务器的wmi

引用来自“肖国颖”的评论

引用来自“黄金比”的评论

不知道远程调用行不行呢?请博主明确一下。 你指的是非本机吗?我测试的方式就是一台linux运行程序指定ip调用另一台win服务器的wmi

收到,谢博主,试下先!

文明上网,理性发言

文明上网,理性发言 回到页首 | 回到评论列表

关闭相关文章阅读

© 开源中国(OsChina.NET) | 关于我们 | 广告联系 | @新浪微博 | 开源中国手机版 | 粤ICP备12009483号-3 开源中国手机客户端: Android iPhone WP7

聊聊并发(六)——ConcurrentLinkedQueue的实现原理分析

Posted on

聊聊并发(六)——ConcurrentLinkedQueue的实现原理分析

分享到

百度分享

聊聊并发(六)——ConcurrentLinkedQueue的实现原理分析

作者 方腾飞 发布于 一月 09, 2013 | 5 评论

1. 引言

在并发编程中我们有时候需要使用线程安全的队列。如果我们要实现一个线程安全的队列有两种实现方式:一种是使用阻塞算法,另一种是使用非阻塞算法。使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现,而非阻塞的实现方式则可以使用循环CAS的方式来实现,本文让我们一起来研究下Doug Lea是如何使用非阻塞的方式来实现线程安全队列ConcurrentLinkedQueue的,相信从大师身上我们能学到不少并发编程的技巧。

2. ConcurrentLinkedQueue的介绍

ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素。它采用了“wait-free”算法来实现,该算法在Michael & Scott算法上进行了一些修改, Michael & Scott算法的详细信息可以参见参考资料一

3. ConcurrentLinkedQueue的结构

我们通过ConcurrentLinkedQueue的类图来分析一下它的结构。

(图1)

ConcurrentLinkedQueue由head节点和tair节点组成,每个节点(Node)由节点元素(item)和指向下一个节点的引用(next)组成,节点与节点之间就是通过这个next关联起来,从而组成一张链表结构的队列。默认情况下head节点存储的元素为空,tair节点等于head节点。 private transient volatile Node tail = head;

4. 入队列

入队列就是将入队节点添加到队列的尾部。为了方便理解入队时队列的变化,以及head节点和tair节点的变化,每添加一个节点我就做了一个队列的快照图。

(图二)

  • 第一步添加元素1。队列更新head节点的next节点为元素1节点。又因为tail节点默认情况下等于head节点,所以它们的next节点都指向元素1节点。
  • 第二步添加元素2。队列首先设置元素1节点的next节点为元素2节点,然后更新tail节点指向元素2节点。
  • 第三步添加元素3,设置tail节点的next节点为元素3节点。
  • 第四步添加元素4,设置元素3的next节点为元素4节点,然后将tail节点指向元素4节点。

通过debug入队过程并观察head节点和tail节点的变化,发现入队主要做两件事情,第一是将入队节点设置成当前队列尾节点的下一个节点。第二是更新tail节点,如果tail节点的next节点不为空,则将入队节点设置成tail节点,如果tail节点的next节点为空,则将入队节点设置成tail的next节点,所以tail节点不总是尾节点,理解这一点对于我们研究源码会非常有帮助。

上面的分析让我们从单线程入队的角度来理解入队过程,但是多个线程同时进行入队情况就变得更加复杂,因为可能会出现其他线程插队的情况。如果有一个线程正在入队,那么它必须先获取尾节点,然后设置尾节点的下一个节点为入队节点,但这时可能有另外一个线程插队了,那么队列的尾节点就会发生变化,这时当前线程要暂停入队操作,然后重新获取尾节点。让我们再通过源码来详细分析下它是如何使用CAS算法来入队的。 public boolean offer(E e) { if (e == null) throw new NullPointerException(); //入队前,创建一个入队节点 Node n = new Node(e); retry: //死循环,入队不成功反复入队。 for (;;) { //创建一个指向tail节点的引用 Node t = tail; //p用来表示队列的尾节点,默认情况下等于tail节点。 Node p = t; for (int hops = 0; ; hops++) { //获得p节点的下一个节点。 Node next = succ(p); //next节点不为空,说明p不是尾节点,需要更新p后在将它指向next节点 if (next != null) { //循环了两次及其以上,并且当前节点还是不等于尾节点 if (hops > HOPS && t != tail) continue retry; p = next; } //如果p是尾节点,则设置p节点的next节点为入队节点。 else if (p.casNext(null, n)) { //如果tail节点有大于等于1个next节点,则将入队节点设置成tair节点,更新失败了也 没关系,因为失败了表示有其他线程成功更新了tair节点。 if (hops >= HOPS) casTail(t, n); // 更新tail节点,允许失败 return true; } // p有next节点,表示p的next节点是尾节点,则重新设置p节点 else { p = succ(p); } } } }

从源代码角度来看整个入队过程主要做二件事情。第一是定位出尾节点,第二是使用CAS算法能将入队节点设置成尾节点的next节点,如不成功则重试。

第一步定位尾节点。tail节点并不总是尾节点,所以每次入队都必须先通过tail节点来找到尾节点,尾节点可能就是tail节点,也可能是tail节点的next节点。代码中循环体中的第一个if就是判断tail是否有next节点,有则表示next节点可能是尾节点。获取tail节点的next节点需要注意的是p节点等于p的next节点的情况,只有一种可能就是p节点和p的next节点都等于空,表示这个队列刚初始化,正准备添加第一次节点,所以需要返回head节点。获取p节点的next节点代码如下 final Node succ(Node p) { Node next = p.getNext(); return (p == next) ? head : next; }

第二步设置入队节点为尾节点。p.casNext(null, n)方法用于将入队节点设置为当前队列尾节点的next节点,p如果是null表示p是当前队列的尾节点,如果不为null表示有其他线程更新了尾节点,则需要重新获取当前队列的尾节点。

hops的设计意图。上面分析过对于先进先出的队列入队所要做的事情就是将入队节点设置成尾节点,doug lea写的代码和逻辑还是稍微有点复杂。那么我用以下方式来实现行不行? public boolean offer(E e) { if (e == null) throw new NullPointerException(); Node n = new Node(e); for (;;) { Node t = tail; if (t.casNext(null, n) && casTail(t, n)) { return true; } } }

让tail节点永远作为队列的尾节点,这样实现代码量非常少,而且逻辑非常清楚和易懂。但是这么做有个缺点就是每次都需要使用循环CAS更新tail节点。如果能减少CAS更新tail节点的次数,就能提高入队的效率,所以doug lea使用hops变量来控制并减少tail节点的更新频率,并不是每次节点入队后都将 tail节点更新成尾节点,而是当 tail节点和尾节点的距离大于等于常量HOPS的值(默认等于1)时才更新tail节点,tail和尾节点的距离越长使用CAS更新tail节点的次数就会越少,但是距离越长带来的负面效果就是每次入队时定位尾节点的时间就越长,因为循环体需要多循环一次来定位出尾节点,但是这样仍然能提高入队的效率,因为从本质上来看它通过增加对volatile变量的读操作来减少了对volatile变量的写操作,而对volatile变量的写操作开销要远远大于读操作,所以入队效率会有所提升。

private static final int HOPS = 1;

还有一点需要注意的是入队方法永远返回true,所以不要通过返回值判断入队是否成功。

5. 出队列

出队列的就是从队列里返回一个节点元素,并清空该节点对元素的引用。让我们通过每个节点出队的快照来观察下head节点的变化。

从上图可知,并不是每次出队时都更新head节点,当head节点里有元素时,直接弹出head节点里的元素,而不会更新head节点。只有当head节点里没有元素时,出队操作才会更新head节点。这种做法也是通过hops变量来减少使用CAS更新head节点的消耗,从而提高出队效率。让我们再通过源码来深入分析下出队过程。 public E poll() { Node h = head; // p表示头节点,需要出队的节点 Node p = h; for (int hops = 0;; hops++) { // 获取p节点的元素 E item = p.getItem(); // 如果p节点的元素不为空,使用CAS设置p节点引用的元素为null,如果成功则返回p节点的元素。 if (item != null && p.casItem(item, null)) { if (hops >= HOPS) { //将p节点下一个节点设置成head节点 Node q = p.getNext(); updateHead(h, (q != null) ? q : p); } return item; } // 如果头节点的元素为空或头节点发生了变化,这说明头节点已经被另外一个线程修改了。那么获取p节点的下一个节点 Node<> next = succ(p); // 如果p的下一个节点也为空,说明这个队列已经空了 if (next == null) { // 更新头节点。 updateHead(h, p); break; } // 如果下一个元素不为空,则将头节点的下一个节点设置成头节点 p = next; } return null; }

首先获取头节点的元素,然后判断头节点元素是否为空,如果为空,表示另外一个线程已经进行了一次出队操作将该节点的元素取走,如果不为空,则使用CAS的方式将头节点的引用设置成null,如果CAS成功,则直接返回头节点的元素,如果不成功,表示另外一个线程已经进行了一次出队操作更新了head节点,导致元素发生了变化,需要重新获取头节点。

6. 参考资料

#

作者介绍

方腾飞,花名清英,淘宝资深开发工程师,关注并发编程,目前在广告技术部从事无线广告联盟的开发和设计工作。个人博客:http://ifeve.com 微博:http://weibo.com/kirals欢迎通过我的微博进行技术交流。

感谢张龙对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。

相关内容

您好,陌生人!

您需要 注册一个InfoQ账号 或者 登录 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

社区评论 Watch Thread

CAS 描述有错 by lin lirs Posted 10/01/2013 05:35 Re: CAS 描述有错 by 方 腾飞 Posted 11/01/2013 03:10

请教大师,有个地方不是很明白 by huang shuihua Posted 18/01/2013 02:58 Re: 请教大师,有个地方不是很明白 by 方 腾飞 Posted 18/01/2013 03:40

看着不过瘾,买了本书 by 杨 亮 Posted 04/03/2013 01:42

CAS 描述有错 10/01/2013 05:35 by lin lirs

“它采用了“wait-free”算法(即CAS算法)来实现”, CAS不是指算法,而是一个原子操作,wait-free不等同CAS。 en.wikipedia.org/wiki/Compare-and-swap

Re: CAS 描述有错 11/01/2013 03:10 by 方 腾飞

的确!CAS是一个原子操作指令,可以用来实现“wait-free”算法。这里用“既CAS算法”的确不太合适,我加上的初衷是希望读者能很好的理解“wait-free”算法,但这样会产生一些歧义,所以还是删掉比较合适,感谢您的纠正。

请教大师,有个地方不是很明白 18/01/2013 02:58 by huang shuihua

(如果tail节点的next节点不为空,则将入队节点设置成tail节点,如果tail节点的next节点为空,则将入队节点设置成tail的next节点,所以tail节点不总是尾节点),这个还是不是很明白,能否有更加清晰一点的原理图show一下,谢谢!

Re: 请教大师,有个地方不是很明白 18/01/2013 03:40 by 方 腾飞

tail节点并总是尾节点。入队的时候,入队节点要放在队列的尾部,那首先要定位尾节点是哪个节点?所以这里通过tail节点来定位尾节点。尾节点要么是tail节点,要么是tail的next节点。所以入队会有两种情况 情况1:tail节点的next节点不为空,那么插入后队列变成 旧的tail节点->旧tail节点的next节点->入队节点(新tail节点) 情况2:tail节点的next节点为空,那么插入后队列变成 tail节点->入队节点

看着不过瘾,买了本书 04/03/2013 01:42 by 杨 亮

聊聊并发这个系列都看了,结合内存模型系列,但还是看着不过瘾,买了本书看。

关闭

**by

发布于

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p 当有人回复此评论时请E-mail通知我

关闭 主题 您的回复

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p 当有人回复此评论时请E-mail通知我 关闭

深度内容

Juergen Fesslmeier谈端到端的JavaScript开发

Juergen Fesslmeier 七月 02, 2013

设计模式自动化

Gael Fraiteur and Yan Cui 七月 01, 2013

设计指尖上的世界:移动用户界面一瞥

Forrest Shull 六月 28, 2013

成功的根本—集成的ALM工具

Dave West 六月 28, 2013

书评:验收测试驱动开发实践指南

Manuel Pais 六月 26, 2013

跨终端的web

舒文亮 六月 26, 2013

Close E-mail 密码

使用Google账号登录 使用Microsoft账号登录 忘记密码? InfoQ账号使用的E-mail 发送邮件

重新登录 重新发送激活信息 重新发送

重新登录 没有用户名?

点击注册 ")")")")")")")")