This is my demo:
Code:
package com.broada;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.HashMap;
import java.util.Set;
public class MapTest {
/**
* @param args
*/
private HashMap<String, String> map = new HashMap<String,String>();
private static MapTest mapTest = new MapTest();
private static int getPid() {
// get PID
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
String name = runtime.getName(); // format: "pid@hostname"
try {
return Integer.parseInt(name.substring(0, name.indexOf('@')));
} catch (Exception e) {
return -1;
}
}
//producer
class Producer extends Thread{
public Producer(String name){
super(name);
}
public void run(){
while(true){
synchronized (map) {
String k = "pid:" + getPid() + "-" + Thread.currentThread().getName() + System.currentTimeMillis();
String v = "";
map.put(k, v);
System.out.println("pid:" + getPid() + "-" + Thread.currentThread().getName() + ": 生产key为" + k.toString() + " map size is " + map.size());
map.notifyAll();
}
try {
Thread.sleep((int)(5000*Math.random()));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//customer
class Customer extends Thread{
public Customer(String name){
super(name);
}
public void run(){
while(true){
synchronized(map){
while(map.isEmpty()){
try {
System.out.println("pid:" + getPid() + "-" + Thread.currentThread().getName() + ": map is empty,wait!");
map.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
map.notifyAll();
Set<String> keySet = map.keySet();
Object[] keyArray = keySet.toArray();
map.remove(keyArray[0]);
System.out.println("pid:" + getPid() + "-" + Thread.currentThread().getName() + " 消费key为" + keyArray[0].toString() + " map size is " + map.size());
try {
Thread.sleep((int)(5000*Math.random()));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
mapTest.new Producer("Producer").start();
mapTest.new Producer("Producer").start();
mapTest.new Producer("Producer").start();
mapTest.new Customer("Customer").start();
mapTest.new Customer("Customer").start();
}
}
Here is my tc-config.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!--
All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved.
-->
<tc:tc-config xmlns:tc="http://www.terracotta.org/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.terracotta.org/schema/terracotta-6.xsd">
<!-- Server is colocated with client and DSO is listening on
default port (9510). -->
<servers>
<server host="127.0.0.1" name="server1"/>
</servers>
<!-- Tell DSO where to put the generated client logs.
See the Terracotta Configuration Guide and Reference for additional
information. -->
<clients>
<logs>H:/soft/Terracotta/terracotta-3.6.2/client-logs</logs>
</clients>
<application>
<dso>
<!-- The app requires these custom objects/classes to be shared - the following declarations
tell DSO which ones they are. When the app runs under DSO, instances of these classes
will broadcast changes in their state.
A best practice (and an MVC pattern) when writing an app that you intend to cluster via Terracotta is to group the
classes you want to share under a single package. This makes the list of instrumented classes more concise.
The following <include> instruments all of the classes found in all of the
packages of our sample app. -->
<instrumented-classes>
<include>
<class-expression>com.*</class-expression>
</include>
</instrumented-classes>
<roots>
<root>
<field-name>com.broada.MapTest.mapTest</field-name>
</root>
</roots>
<locks>
<autolock>
<method-expression>void com.broada.MapTest.Producer.run()</method-expression>
<lock-level>write</lock-level>
</autolock>
<autolock>
<method-expression>void com.broada.MapTest.Customer.run()</method-expression>
<lock-level>write</lock-level>
</autolock>
</locks>
</dso>
</application>
</tc:tc-config>
After start the server, run the demo,this is the error:
H:\soft\Terracotta\terracotta-3.6.2\platform\bin>dso-java.bat -cp MapTest.jar c
m.broada.MapTest
Starting Terracotta client...
2013-05-20 09:27:23,796 INFO - Terracotta 3.6.2, as of 20120412-135519 (Revisio
20065 by cruise@rh5vmo113.terracotta.lan from 3.6.2)
2013-05-20 09:27:24,546 INFO - Successfully loaded base configuration from file
at 'H:\soft\Terracotta\terracotta-3.6.2\platform\bin\tc-config.xml'.
2013-05-20 09:27:24,609 INFO - Log file: 'H:\soft\Terracotta\terracotta-3.6.2\c
ient-logs\terracotta-client.log'.
2013-05-20 09:27:26,468 INFO - Connection successfully established to server at
127.0.0.1:9510
pid:4224-Customer: map is empty,wait!
com.tc.object.tx.UnlockedSharedObjectException:
*********************************************************************
Attempt to access a shared object outside the scope of a shared lock.
All access to shared objects must be within the scope of one or more
shared locks defined in your Terracotta configuration.
Caused by Thread: Producer in VM(1)
Shared Object Type: java.util.HashMap
The cause may be one or more of the following:
* Terracotta locking was not configured for the shared code.
* The code itself does not have synchronization that Terracotta
can use as a boundary.
* The class doing the locking must be included for instrumentation.
* The object was first locked, then shared.
For more information on how to solve this issue, see:
http://www.terracotta.org/kit/reflector?kitID=default&pageID=usoe
*********************************************************************
at com.tc.object.tx.ClientTransactionManagerImpl.getTransaction(ClientT
ansactionManagerImpl.java:209)
at com.tc.object.tx.ClientTransactionManagerImpl.checkWriteAccess(Clien
TransactionManagerImpl.java:220)
at com.tc.object.bytecode.ManagerImpl.checkWriteAccess(ManagerImpl.java
519)
at com.tc.object.bytecode.ManagerUtil.checkWriteAccess(ManagerUtil.java
439)
at java.util.HashMap.put(Unknown Source)
at com.broada.MapTest$Producer.run(MapTest.java:43)
Exception in thread "Producer" com.tc.object.tx.UnlockedSharedObjectException:
*********************************************************************
Attempt to access a shared object outside the scope of a shared lock.
All access to shared objects must be within the scope of one or more
shared locks defined in your Terracotta configuration.
Caused by Thread: Producer in VM(1)
Shared Object Type: java.util.HashMap
The cause may be one or more of the following:
* Terracotta locking was not configured for the shared code.
* The code itself does not have synchronization that Terracotta
can use as a boundary.
* The class doing the locking must be included for instrumentation.
* The object was first locked, then shared.
So,how to configuration the label of autolock in the tc-config.xml?