最近想研究一下Coroutines(協程)並在java項目中進行應用,但是發現現在大部分資料講的是unity、lua、alang等方面的應用,java上講的確實不太多。所以今天想把這幾天的學習結果寫出來和大家一起分享。可能有一些理解不一定對,請大家批評指正。
大家知道,線程是程序執行流的最小單位,但是可以把協程認爲是比線程更小的執行單元。
協程和線程可以設計成1:N的模式,即一個線程容器中可以放置多個協程。
每個協程有自己的上下文信息,可以在協程之間進行切換,
而且這種切換是用戶態的切換,不像線程切換需要深入到操作系統內核纔可以,
所以協程比線程更加節省資源,更加快速。而且很適合項目中有低速IO和高速CPU進行協調調度的問題。
目前我瞭解到可以在java程序中應用的協程組件有以下幾種:
javaflow:http://commons.apache.org/sandbox/commons-javaflow/
Coroutines:https://github.com/offbynull/coroutines
Kilim:https://github.com/kilim/kilim
我個人目前只嚐了前面兩種,其中Coroutines中作者在javaflow問題的基礎上重新設計的一種,比javaflow在狀態的變化中運行的更加快速、而且提供了maven和ant兩種方法、更好的支持java8等優點。
以下我以Coroutines組件爲例說一下具體實現過程:
我本身用的是ant插件,其中主要jar包如下:
lib/ant-plugin-1.1.1-shaded.jar
lib/commons.jar
lib/user-1.1.1.jar
1、創建一個工程
2、引入以上jar包
3、編寫相應程序,如下:
import com.offbynull.coroutines.user.Continuation;
import com.offbynull.coroutines.user.Coroutine;
import com.offbynull.coroutines.user.CoroutineRunner;
public class App implements Coroutine {
public static void main(String[] args) {
CoroutineRunner r = new CoroutineRunner(new App());
boolean flag = r.execute();
while (flag) {
flag = r.execute();
}
}
public void run(Continuation c) throws Exception {
System.out.println("started");
for (int i = 0; i < 10; i++) {
echo(c, i);
}
}
private void echo(Continuation c, int x) {
System.out.println(x);
c.suspend();
}
}
4、編寫build.xml,對class文件進行重新裝配
<?xml version="1.0" encoding="UTF-8"?>
<project name="CoroutiesTest" default="run" basedir=".">
<description>use jar test</description>
<property name="src" value="src" />
<property name="classes" value="bin/classes" />
<target name="clean">
<delete dir="${classes}" />
</target>
<pathconvert property="lib" pathsep=" ">
<mapper>
<chainedmapper>
<flattenmapper />
<globmapper from="*" to="lib/*" />
</chainedmapper>
</mapper>
<fileset dir="lib">
<include name="*.jar" />
</fileset>
</pathconvert>
<property name="libs" value="${lib}" />
<echo>libs ${libs}</echo>
<target name="init">
<mkdir dir="${classes}" />
</target>
<taskdef name="InstrumentTask" classname="com.offbynull.coroutines.antplugin.InstrumentTask">
<classpath>
<fileset dir="lib">
<include name="*.jar" />
</fileset>
</classpath>
</taskdef>
<target name="compile" depends="init" description="comile target">
<javac srcdir="${src}" destdir="${classes}" includeantruntime="true">
<classpath>
<fileset dir="lib">
<include name="*.jar" />
</fileset>
</classpath>
</javac>
<InstrumentTask classpath="." sourceDirectory="${classes}" targetDirectory="${classes}"/>
</target>
<tstamp />
<property name="jarfilename" value="${ant.project.name}.jar" />
<target name="jar" depends="compile" description="make jar file">
<jar jarfile="${jarfilename}" basedir="${classes}">
<manifest>
<attribute name="Main-Class" value="App" />
<attribute name="Class-Path" value="${libs}" />
</manifest>
</jar>
</target>
<target name="run" depends="jar">
<java jar="${jarfilename}" fork="true">
</java>
</target>
</project>
5、運行結果:
Buildfile: D:\MyProgram\java8\CoroutiesTest\build.xml
[echo] libs lib/ant-plugin-1.1.1-shaded.jar lib/commons.jar lib/user-1.1.1.jar
init:
compile:
[javac] Compiling 1 source file to D:\MyProgram\java8\CoroutiesTest\bin\classes
[InstrumentTask] Classpath for instrumentation is as follows: [., D:\Program Files\Java\jre8\lib\charsets.jar, D:\Program Files\Java\jre8\lib\deploy.jar, D:\Program Files\Java\jre8\lib\ext\access-bridge-64.jar, D:\Program Files\Java\jre8\lib\ext\cldrdata.jar, D:\Program Files\Java\jre8\lib\ext\dnsns.jar, D:\Program Files\Java\jre8\lib\ext\jaccess.jar, D:\Program Files\Java\jre8\lib\ext\jfxrt.jar, D:\Program Files\Java\jre8\lib\ext\localedata.jar, D:\Program Files\Java\jre8\lib\ext\nashorn.jar, D:\Program Files\Java\jre8\lib\ext\sunec.jar, D:\Program Files\Java\jre8\lib\ext\sunjce_provider.jar, D:\Program Files\Java\jre8\lib\ext\sunmscapi.jar, D:\Program Files\Java\jre8\lib\ext\sunpkcs11.jar, D:\Program Files\Java\jre8\lib\ext\zipfs.jar, D:\Program Files\Java\jre8\lib\javaws.jar, D:\Program Files\Java\jre8\lib\jce.jar, D:\Program Files\Java\jre8\lib\jfr.jar, D:\Program Files\Java\jre8\lib\jfxswt.jar, D:\Program Files\Java\jre8\lib\jsse.jar, D:\Program Files\Java\jre8\lib\management-agent.jar, D:\Program Files\Java\jre8\lib\plugin.jar, D:\Program Files\Java\jre8\lib\resources.jar, D:\Program Files\Java\jre8\lib\rt.jar, D:\Program Files\Java\jre8\lib\security\local_policy.jar, D:\Program Files\Java\jre8\lib\security\US_export_policy.jar]
[InstrumentTask] Creating instrumenter...
[InstrumentTask] Processing D:\MyProgram\java8\CoroutiesTest\bin\classes ...
[InstrumentTask] Instrumenting D:\MyProgram\java8\CoroutiesTest\bin\classes\App.class
[InstrumentTask] Instrumenting D:\MyProgram\java8\CoroutiesTest\bin\classes\ICallBack.class
[InstrumentTask] Instrumenting D:\MyProgram\java8\CoroutiesTest\bin\classes\MessageProcess$1.class
[InstrumentTask] Instrumenting D:\MyProgram\java8\CoroutiesTest\bin\classes\MessageProcess.class
[InstrumentTask] Instrumenting D:\MyProgram\java8\CoroutiesTest\bin\classes\RemoteClass.class
[InstrumentTask] Instrumenting D:\MyProgram\java8\CoroutiesTest\bin\classes\Test$1.class
[InstrumentTask] Instrumenting D:\MyProgram\java8\CoroutiesTest\bin\classes\Test.class
jar:
[jar] Building jar: D:\MyProgram\java8\CoroutiesTest\CoroutiesTest.jar
run:
[java] started
[java] 0
[java] 1
[java] 2
[java] 3
[java] 4
[java] 5
[java] 6
[java] 7
[java] 8
[java] 9
BUILD SUCCESSFUL
Total time: 3 seconds
好了,大功告成!希望能給想學習協程的同行們提供幫助,也希望大家能夠把一些自己的理解想出來,大家一起分享學習,共同進步,謝謝!