public class Practice {
public static void main(String[] args) {
Test t1 = new Test();
//System.out.println( Test.countObject() );
Test t2 = new Test(9);
//System.out.println( Test.countObject() );
Test t3 = new Test("Soham");
System.out.println( Test.countObject() );
}
}
class Test{
static int count = 0;
static int countObject(){
count++;
//System.out.println(count);
return count;
}
public Test(){
}
public Test(int n){
}
public Test (String s){
}
}
In this code , I'm trying print the count of objects by calling countObject() (don't want to call by a constructor) bt my count is not updated even after creating 3 objects. my count is only updated if I call Test.countObject() thrice . Why this is happening ? and how can I solve the problem (count object in a single call by countObject Function) ?
Related
I came across the following excerpt while reading on visibility guarantees provided by the JVM when reading volatile variables :
"When thread A writes to a volatile variable and subsequently thread B reads that same variable, the values of ALL variables that were visible to A prior to writing to the volatile variable become visible to B AFTER reading the volatile variable."
I have a question around this guarantee of JVM. Consider the below set of classes :
public class Test {
public static void main(String[] args) throws InterruptedException {
POJO p = new POJO();
new Th1(p).start();
new Th2(p).start();
}
}
public class Th1 extends Thread {
private POJO p1 = null;
public Th1(POJO obj) {
p1 = obj;
}
#Override
public void run() {
p1.a = 10; // t = 1
p1.b = 10; // t = 2
p1.c = 10; // t = 5;
System.out.println("p1.b val: " + p1.b); // t = 8
System.out.println("Thread Th1 finished"); // t = 9
}
}
public class Th2 extends Thread {
private POJO p2 = null;
public Th2(POJO obj) {
p2 = obj;
}
#Override
public void run() {
p2.a = 30; // t = 3
p2.b = 30; // t = 4
int x = p2.c; // t = 6
System.out.println("p2.b value: " + p2.b); // t = 7
}
}
public class POJO {
int a = 1;
int b = 1;
volatile int c = 1;
}
Imagine the 2 threads Th1 and Th2 run in separate CPUs and the order in which their instructions execute is indicated by the comment in each line (in their run methods). The question I have is that :
When code "int x = p2.c;" executes at t = 6, variables visible to thread Th2 should be refreshed from main memory as per the above para. The main memory then as I understand would have all the writes from Th1 at this point. What value will the variable p2.b show then when it is printed at t = 7?
Will p2.b show value of 10 as its value was refreshed from the read of the volatile variable p2.c?
Or it will retain the value 30 somehow?
For your code, p2.b is not guaranteed to be 10 or 30. The write is a race condition.
"When thread A writes to a volatile variable and subsequently thread B reads that same variable, the values of ALL variables that were visible to A prior to writing to the volatile variable become visible to B AFTER reading the volatile variable."
Your Th2 read of p2.c is not guaranteed to be done after the write of p1.c in Th1.
For the specific order you discussed, the read of p2.c in Th2 will not revert the value of p2.b to 10.
There is no happens before edge between the write of a and the read of a. Since they are conflicting actions (at least one of them is a write) and are on the same address, there is a data-race and as a consequence, program behavior is undefined.
I think the following example explains the behavior of what you are looking for better:
public class Test {
public static void main(String[] args) throws InterruptedException {
POJO p = new POJO();
new Th1(p).start();
new Th2(p).start();
}
}
public class Th1 extends Thread {
private POJO p1 = null;
public Th1(POJO obj) {
p1 = obj;
}
#Override
public void run() {
a=1;
b=1;
}
}
public class Th2 extends Thread {
private POJO p2 = null;
public Th2(POJO obj) {
p2 = obj;
}
#Override
public void run() {
if(p.b==1)println("a must be 1, a="+p2.a);
}
}
public class POJO {
int a = 0;
volatile int b = 0;
}
There is a happens before edge between the write of a and the write of b (program order rule)
There is a happens before edge between the write of b and a subsequent read of b (volatile variable rule)
There is a happens before edge between the read of b and the read of a (program order rule)
Since the happens before relation is transitive, there is a happens before edge between the write of a and the read of a. So the second thread should see the a=1 from the first thread.
I have a class Card to represent a deck of cards as an array of objects Card[], with methods to shuffle and print the deck. I have a test class TestCard to generate the deck (in TestCard) then shuffle and print the deck (as methods in Card.) I get the message
TestCard.java:17: error: cannot find symbol
mydeck.writeDeck();
^
symbol: method writeDeck()
location: variable mydeck of type Card[]
Here is the Card.java code.
public class Card {
public static final int NUMCARDS=52;
String suit;
int value;
String name;
public Card() {
suit = " ";
value = 0;
name = " ";
}
public Card(String suit, int value, String name) {
this.suit=suit;
this.value=value;
this.name=name;
}
public void setData(String su,int va, String na) {
suit = su; value = va; name = na;
}
public void writeDeck(Card[] cards) {
int count=0;
for (Card mycard : cards ) {
System.out.print(mycard.name+mycard.suit);
count++;
if (count==13) {
System.out.println();
count= 0;
}
}
System.out.println();
}
private void swap(Card[] arr,int i, int j) {
Card temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
public void shuffle(Card[] carr) {
int index;
for (int i=NUMCARDS-1; i>0; i--) {
index = (int) (Math.random() * (i+1));
swap(carr, i, index);
}
}
}
and here is TestCode.java code
public class TestCard {
public static final int NUMCARDS=52;
public static void main(String args[]) {
Card[] mydeck = new Card[NUMCARDS];
for (int i=0; i<NUMCARDS; i++) {
int j=i%13+1;
String v;
v = Integer.toString(j);
String s;
if (i<13) s="C";
else if (i<26) s="D";
else if (i<39) s="H";
else s="S";
mydeck[i] = new Card(s,j,v);
}
System.out.print(mydeck[5].suit+mydeck[5].value);
mydeck.writeDeck();
mydeck.shuffle();
mydeck.writeDeck();
}
}
I have spent 8 hours trying various fixes, using tutorials from various we sites, but have not succeeded.
mydeck.writeDeck(); is trying to call the writeDeck() method of the instance mydeck. But if you look at the code:
Card[] mydeck = new Card[NUMCARDS];
my deck is not a Card object, it's an array of Card objects. According to your code, you must pass in a Card[] as a parameter.
Turn .writeDeck(Card[] cards) into a static method:
public static void writeDeck(Card[] cards)
and then invoke the method like so:
Card.writeDeck(mydeck)
Marvin's answer worked like a charm. According to the Oracle documentation, for a method to work on an array of objects, the method must be defined for the object. But you can't just simply say arrayvar.method(). You have to say Objectclass.method(arrayvar). Good news is you can pass two array variables if you are working with both.
Concurrent writing elements into the ConcurrentHashMap admits element. Requirements: writing must be done in different threads. Is there way to use advantages of the ConcurrentHashMap and do writing without blocking and sleeping?
Is there good code for iterator that accessed from different treads. Or is there other good variant to keep ieratian looking on the effectively-final requirement?
public class Task3v2 {
public static void main(String[] args) {
System.out.println("ConcurrentHashMap : "+timeIt(new ConcurrentHashMap<Integer, String>()));
}
static Iterator<Integer> integerIterator;
static {createIterator();}
private static void createIterator() {
integerIterator=
Stream.iterate(0, i -> i + 1).limit(100).collect(Collectors.toList()).iterator();
}
public static double timer(Runnable block) {
long start = System.nanoTime();
try {
block.run();
} finally {
long end = System.nanoTime();
return(end - start);
}
}
public static double timeIt(Map<Integer, String> map){
return timer(
()->{
new Thread(()->{
fillMap(map);
System.out.println("invoked");
readMap(map);
}).start();
});
}
private static void fillMap(Map<Integer, String> map){
int[] index = new int[1];
String[] tmp = new String[1];
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i = 0; i< 100; i++){
index[0] = i;
tmp[0] = "Name"+i;
new Thread(()->{
int a = integerIterator.next();
System.out.println("a :"+a);
map.put(a,"Name"+a);
}
).start();
}
}
private static void readMap(Map<Integer, String> map){
int[] index2 = new int[1];
for(int i = 0; i< 100; i++){
index2[0]=i;
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
System.out.println("map.get(index2[0]) :"+map.get(index2[0]));
}).start();
}
}
}
Finally the map must pass following tests:
public class Task3Test {
static ConcurrentHashMap<Integer, String> map;
#BeforeClass
public static void fillMap(){
map = new ConcurrentHashMap<>();
timeIt(map);
}
#Test
public void elementPresenceTest(){
//GIVEN
//map;
//WHEN
List<Integer> actualPresenceList = Stream.iterate(0, i -> i + 1).limit(100)
.filter(n->(map.entrySet().stream().map(Map.Entry::getKey)
.anyMatch(m->(n.equals(m))))).collect(Collectors.toList());
actualPresenceList.forEach(System.out::println);
System.out.println("size"+actualPresenceList.size());
//THEN
List<Integer>expectedPresenceList = Stream.iterate(0, i -> i + 1).limit(100).collect(Collectors.toList());
assertThat(actualPresenceList, Matchers.contains(expectedPresenceList));
}
#Test
public void elementAmountTest() {
assertThat(map.entrySet(), Matchers.hasSize(100));
}
}
Iterator is not acceptable for concurrency. Solution is:
static Queue integerQueue = Stream.iterate(0, i -> i + 1).limit(100).collect(Collectors.toCollection(LinkedBlockingQueue::new));
There is needed to keep sleeping for the readMap() method to provide time for the writing method. If there is needed to keep any data structure on adding new elements in concurrency environment, it should be used queue instead of map.
How can I cancel a thread from another class fetching/refreshing location. I am able to cancel a thread from within the same class. But I am unable to do this across classes. Declaring the GPSThread static did not help. Can anyone please guide?
Class1:
public class GPSListener {
/* Other instantiation code */
Dialog busyDialog1 = new Dialog("Refreshing Location...",
new String [] { "Cancel" },
new int [] { Dialog.CANCEL},
Dialog.CANCEL,
Bitmap.getPredefinedBitmap(Bitmap.HOURGLASS))
{
public void fieldChanged(Field field1, int context1)
{
GPSHandler.requestStop();
busyDialog1.cancel();
}
};
public String refreshCoordinates() {
String test = "nothing";
if (GPSHandler.isStopRequested())
{
GPSHandler.stopRequested = false;
return null;
}
GPSHandler.getInstance().setListener(this);
GPSHandler.getInstance().requestLocationUpdates();
if (GPSHandler.isStopRequested())
{
GPSHandler.stopRequested = false;
return null;
}
busyDialog1.setEscapeEnabled(false);
busyDialog1.show();
return test;
}
public void onLocationReceived(Coordinates location) {
lblLatitude.setText(Double.toString(location.getLatitude()));
lblLongitude.setText(Double.toString(location.getLongitude()));
busyDialog1.cancel();
}
}
Class 2:
public class GPSHandler {
private GPSThread _gpsThread;
private Coordinates _location;
private boolean _gotLocation;
private GPSListener _listener;
/** this class will be a Singleton, as the device only has one GPS system */
private static GPSHandler _instance;
/** #return the Singleton instance of the GPSHandler */
public static GPSHandler getInstance() {
if (_instance == null) {
_instance = new GPSHandler();
}
return _instance;
}
public static boolean stopRequested = false;
public synchronized static void requestStop() {
stopRequested = true;
}
public synchronized static boolean isStopRequested() {
return stopRequested;
}
/** not publicly accessible ... use getInstance() */
private GPSHandler() {
}
/** call this to trigger a new location fix */
public void requestLocationUpdates() {
if (_gpsThread == null || !_gpsThread.isAlive()) {
_gpsThread = new GPSThread();
_gpsThread.start();
}
}
public void setListener(GPSListener listener) {
// only supports one listener this way
_listener = listener;
}
private void setLocation(final Coordinates value) {
_location = value;
if (value.getLatitude() != 0.0 || value.getLongitude() != 0.0) {
_gotLocation = true;
if (_listener != null) {
// this assumes listeners are UI listeners, and want callbacks on the UI thread:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
_listener.onLocationReceived(value);
}
});
}
}
}
private class GPSThread extends Thread {
private void getLocationFromGoogle() {
try {
int cellID = GPRSInfo.getCellInfo().getCellId();
int lac = GPRSInfo.getCellInfo().getLAC();
String urlString2 = "http://www.google.com/glm/mmap";
// Open a connection to Google Maps API
ConnectionFactory connFact = new ConnectionFactory();
ConnectionDescriptor connDesc;
connDesc = connFact.getConnection(urlString2);
HttpConnection httpConn2;
httpConn2 = (HttpConnection)connDesc.getConnection();
httpConn2.setRequestMethod("POST");
// Write some custom data to Google Maps API
OutputStream outputStream2 = httpConn2.openOutputStream();//getOutputStream();
writeDataGoogleMaps(outputStream2, cellID, lac);
// Get the response
InputStream inputStream2 = httpConn2.openInputStream();//getInputStream();
DataInputStream dataInputStream2 = new DataInputStream(inputStream2);
// Interpret the response obtained
dataInputStream2.readShort();
dataInputStream2.readByte();
final int code = dataInputStream2.readInt();
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert(code + "");
}
});
if (code == 0) {
final double latitude = dataInputStream2.readInt() / 1000000D;
final double longitude = dataInputStream2.readInt() / 1000000D;
setLocation(new Coordinates(latitude, longitude, 0.0f));
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert(latitude+"-----"+longitude);
}
});
dataInputStream2.readInt();
dataInputStream2.readInt();
dataInputStream2.readUTF();
} else {
System.out.println("Error obtaining Cell Id ");
}
outputStream2.close();
inputStream2.close();
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
private void tryGetLocationFromDevice() {
_gotLocation = false;
try {
Criteria myCriteria = new Criteria();
myCriteria.setCostAllowed(false);
LocationProvider myLocationProvider = LocationProvider.getInstance(myCriteria);
try {
Location myLocation = myLocationProvider.getLocation(300);
setLocation(myLocation.getQualifiedCoordinates());
} catch ( InterruptedException iex ) {
System.out.println(iex.getMessage());
} catch ( LocationException lex ) {
System.out.println(lex.getMessage());
}
} catch ( LocationException lex ) {
System.out.println(lex.getMessage());
}
if (!_gotLocation) {
getLocationFromGoogle();
}
}
public void run() {
int bbMapsHandle = CodeModuleManager.getModuleHandle("net_rim_bb_lbs"); // OS 4.5 - 6.0
int bbMapsHandle60 = CodeModuleManager.getModuleHandle("net_rim_bb_maps"); // OS 6.0
if (bbMapsHandle > 0 || bbMapsHandle60 > 0) {
tryGetLocationFromDevice();
} else {
getLocationFromGoogle();
}
}
}
private void writeDataGoogleMaps(OutputStream out, int cellID, int lac) throws IOException {
DataOutputStream dataOutputStream = new DataOutputStream(out);
dataOutputStream.writeShort(21);
dataOutputStream.writeLong(0);
dataOutputStream.writeUTF("en");
dataOutputStream.writeUTF("Android");
dataOutputStream.writeUTF("1.0");
dataOutputStream.writeUTF("Web");
dataOutputStream.writeByte(27);
dataOutputStream.writeInt(0);
dataOutputStream.writeInt(0);
dataOutputStream.writeInt(3);
dataOutputStream.writeUTF("");
dataOutputStream.writeInt(cellID);
dataOutputStream.writeInt(lac);
dataOutputStream.writeInt(0);
dataOutputStream.writeInt(0);
dataOutputStream.writeInt(0);
dataOutputStream.writeInt(0);
dataOutputStream.flush();
}
}
Your GPSThread object is currently declared as a private inner class within GPSHandler. If you want to stop execution (or indeed do anything with it) from outside the scope of GPSHandler you will need to mark it as public. You will also need to provide some public mechanism (e.g. a stop() method) to cancel the thread execution.
The most common way of doing this is to have a boolean flag inside your thread (e.g shouldStop) which is checked within your main execution loop inside run() to see if it should stop. When the stop() method is called shouldStop is set to true and your Thread will stop.
Here's a good example: How to stop threads in Java?
There's two groups of changes you should make.
Change the Stop Requested Flag
First, remember that encapsulation is a good thing in Object-Oriented languages. The isStopRequested() method, or stopRequested variable of the GPSHandler should not be used outside of that class. Your UI's GPSListener should not attempt to use either of those. I would change your GPSHandler to use this:
private static boolean stopRequested = false;
public synchronized static void requestStop() {
stopRequested = true;
}
private synchronized static boolean isStopRequested() {
return stopRequested;
}
Only requestStop() should be public. It looks like you made stopRequested public to allow the GPSListener to reset it. If it needs resetting, let the class that owns that variable do the resetting. For example, in GPSHandler:
/** call this to trigger a new location fix */
public void requestLocationUpdates() {
if (_gpsThread == null || !_gpsThread.isAlive()) {
// reset this stop flag:
stopRequested = false;
_gpsThread = new GPSThread();
_gpsThread.start();
}
}
requestLocationUpdates() is really the method that starts the thread, so it should be where stopRequested gets reset to false.
Also, another reason that you should not make stopRequested public and allow other classes to use it is that this is not generally thread-safe. One of the reasons to wrap stopRequested with the requestStop() and isStopRequested() methods is to add thread-safety. There's many ways to do that, but those two methods achieve thread-safety by being marked with the synchronized keyword.
Change How/Where You Check the Flag
After you make these fixes, you need to change where you check if a stop has been requested. You don't really want to check isStopRequested() in the refreshCoordinates() method. That method involves almost no work. Even though it starts the process of getting a location fix, that only starts a thread, but the actual work of getting the location is done on a background thread (your GPSThread). If requestStop() is called, it's very unlikely that it will be called in the middle of refreshCoordinates(), so that's not where you should check it.
Check isStopRequested() multiple times within the GPSHandler class's methods tryGetLocationFromDevice() and getLocationFromGoogle(). Those are the methods that perform slow processing. Those are the ones you might want to interrupt in the middle. So, something like this:
private void getLocationFromGoogle() {
try {
int cellID = GPRSInfo.getCellInfo().getCellId();
int lac = GPRSInfo.getCellInfo().getLAC();
String urlString2 = "http://www.google.com/glm/mmap";
if (isStopRequested()) return;
// Open a connection to Google Maps API
ConnectionFactory connFact = new ConnectionFactory();
ConnectionDescriptor connDesc;
connDesc = connFact.getConnection(urlString2);
HttpConnection httpConn2;
httpConn2 = (HttpConnection)connDesc.getConnection();
httpConn2.setRequestMethod("POST");
// Write some custom data to Google Maps API
OutputStream outputStream2 = httpConn2.openOutputStream();//getOutputStream();
writeDataGoogleMaps(outputStream2, cellID, lac);
if (isStopRequested()) return;
// Get the response
InputStream inputStream2 = httpConn2.openInputStream();//getInputStream();
DataInputStream dataInputStream2 = new DataInputStream(inputStream2);
// Interpret the response obtained
dataInputStream2.readShort();
dataInputStream2.readByte();
if (isStopRequested()) return;
final int code = dataInputStream2.readInt();
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert(code + "");
}
});
And in tryGetLocationFromDevice(), you could do this (make sure to add the member variable and new method below):
private LocationProvider _locationProvider; // must be a member variable!
public void requestStop() {
if (_locationProvider != null) {
// this will interrupt the _locationProvider.getLocation(300) call
_locationProvider.reset();
}
}
private void tryGetLocationFromDevice() {
_gotLocation = false;
try {
Criteria myCriteria = new Criteria();
myCriteria.setCostAllowed(false);
_locationProvider = LocationProvider.getInstance(myCriteria);
try {
Location myLocation = _locationProvider.getLocation(300);
setLocation(myLocation.getQualifiedCoordinates());
} catch ( InterruptedException iex ) {
// this may be caught if stop requested!!!!
System.out.println(iex.getMessage());
} catch ( LocationException lex ) {
System.out.println(lex.getMessage());
}
} catch ( LocationException lex ) {
System.out.println(lex.getMessage());
}
if (!_gotLocation && !isStopRequested()) {
getLocationFromGoogle();
}
}
Then, call the GPSThread.requestStop() method from the outer GPSHandler.requestStop() method:
public synchronized static void requestStop() {
stopRequested = true;
if (_gpsThread != null) {
_gpsThread.requestStop();
}
}
below is my simple code to start 5 threads, each one calls a wcf service which returns the value sent in, my problem is that the :
public void clien_GetDataCompleted(object sender, GetDataCompletedEventArgs e)
{
lock (sync)
{
count += e.Result;
}
}
works ok and increments the count, but how do i capture when all the threads have completed, does anybody have simple example code on how to call multiple wcf services which use async methods.
public partial class Threading : Form
{
public int count;
ServiceReference1.Service1Client clien = new ServiceReference1.Service1Client();
public Threading()
{
InitializeComponent();
}
private void GetData()
{
clien.GetDataAsync(1);
}
public void DisplayResults()
{
MessageBox.Show(count.ToString());
}
private object sync = new object();
public void clien_GetDataCompleted(object sender, GetDataCompletedEventArgs e)
{
lock (sync)
{
count += e.Result;
}
}
public List<Thread> RunThreads(int count, ThreadStart start)
{
List<Thread> list = new List<Thread>();
for (int i = 0; i <= count - 1; i++)
{
dynamic thread = new Thread(start);
thread.Start();
list.Add(thread);
}
return list;
}
private void button1_Click_1(object sender, EventArgs e)
{
clien.GetDataCompleted += new EventHandler<GetDataCompletedEventArgs>(clien_GetDataCompleted);
ThreadStart WcfCall = new ThreadStart(GetData);
IList<Thread> threads = RunThreads(5, WcfCall);
}
}
many thanks
If you are using .NET 4.0 you can use Task Parallel Library (TPL) and use Tasks instead of Threads. Tasks has more flow control. What you can do with tasks something like
// Wait for all the tasks to finish.
Task.WaitAll(tasks);
Here is example on how to use Tasks and wait for all tasks to finish. here
I have implemented the solution using tasks, the code is below, its works well, let me know if theres any improvement i could do.
public partial class Tasks : Form
{
static ServiceReference1.Service1Client clien = new ServiceReference1.Service1Client();
int count = 0;
public Tasks()
{
InitializeComponent();
}
// Define a delegate that prints and returns the system tick count
Func<object, int> action = (object obj) =>
{
int i = (int)obj;
clien.GetDataAsync(i);
Console.WriteLine("Task={0}, i={1}, Thread={2}", Task.CurrentId, i, Thread.CurrentThread.ManagedThreadId);
return i;
};
public void clien_GetDataCompleted(object sender, GetDataCompletedEventArgs e)
{
count += e.Result;
}
private void button1_Click(object sender, EventArgs e)
{
const int n = 5;
// create async callback delegate from wcf.
clien.GetDataCompleted += new EventHandler<GetDataCompletedEventArgs>(clien_GetDataCompleted);
// Construct started tasks
Task<int>[] tasks = new Task<int>[n];
for (int i = 0; i < n; i++)
{
tasks[i] = Task<int>.Factory.StartNew(action, i);
}
try
{
// Wait for all the tasks to finish.
Task.WaitAll(tasks);
MessageBox.Show(count.ToString());
}
catch
{
}
}
}
cheers