I don't know if this is the best approach so that's why I'm asking your help guys.
This is my problem, I'm developing an app where you have the 'read' button, when the user hit this button then the program start to read some values and save this values in my database, okay ?
So I think when the user hit 'read' I start a thread, that's because the user can do another thing if he wants without the app been freeze.
But I cannot access the values read by this thread.
There's another way to do that ?
EDIT:
private void jtb_readerItemStateChanged(java.awt.event.ItemEvent evt) {
// getting some values provided by the user
if (buttonReaderState()){
if (supervisory == null)
supervisory = new Supervisory(ip, broadcast, deviceID);
supervisory.start();
}
}
// Supervisory class
public void start(){
Scan scan = new Scan();
Thread t = new Thread(scan);
t.start();
threadState = true;
}
class Scan extends Thread{
public void run(){
// inside the tread I have to initiate another 'supervisory' object, is that right ?
Supervisory s = new Supervisory(ip, broadcast, deviceID);
while (threadState){
try {
s.active();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public void active() throws IOException, Exception {
// getting this values from my hardware like temperature and anothers things.
for (int i = 0; i < ois.size(); i++) {
ObjectIdentifier oi = ois.get(i);
//analog input
if (i == 1)
aI = Float.parseFloat(getPresentValue(localDevice, oi));
//analog output
if (i == 2)
aO = Float.parseFloat(getPresentValue(localDevice, oi));
//binary input
if (i == 3)
bI = getBinaryValue(getPresentValue(localDevice, oi));
//binary output
if (i == 4)
bO = getBinaryValue(getPresentValue(localDevice, oi));
}
}
After reading this values I would like to show this values in the interface that I'm building, but it seems that I cannot have access to these values (aI,aO,bI,bO).
Pass a reference to the interface you have. E.g. you can add a JFrame owner field to Supervisory class and pass your values there.
Related
I would just like to ask if how do u listen to a external input forever while u can do events like button clicking, texfield typing, etc.
Like it listens every second, and if it receives a data, it will do something. If it doesnt receive data then it continues to listen for data.
While it listens, I can do events like I mentioned above.
Sorry for my bad english.
The only good way to read from a stream is in a separate thread. For a silly example, if you wanted to update a label with the last byte read, something like this might work:
static void startListening(DataInputStream inputStream, JLabel label) {
new Thread(() -> {
try {
while (true) {
int i = inputStream.read();
if (i < 0) {
updateText(label, "Closed");
break;
} else {
updateText(label, "Latest byte: " + i);
}
}
} catch (Exception e) {
updateText(label, "Error: " + e);
}
}).start();
}
static void updateText(JLabel label, String text) {
SwingUtilities.invokeLater(() -> label.setText(text));
}
I have a ChannelGroup containing 4 clients that have logged in one by one and have been added to the group as they log in through the Netty method handlerAdded.
static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
#Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
channels.add(ctx.channel());
assignGroup(ctx.channel());
}
I later save my ChannelGroup in an object named GameMaster and initialize a game loop that gives each client a chance to play its turn:
static ChannelGroup channels; // contains the actual channels, saved in contructor
public void bettingPhase(boolean isOk) {
int i = 0;
int y = 0;
for (Channel chan : channels) { // Should start on the first client that logged in
Server.MyMessage.Builder message = Server.MyMessage.newBuilder();
message.setKeyword("304");
message.setValue("Please input a contract:");
chan.writeAndFlush(message); // PROBLEM HERE
while (isOk == false) { // Loop to check the playing client's input
Server.MyMessage.Builder message2 = Server.MyMessage.newBuilder();
try {
Thread.sleep(1000);
if (playerAnswer.getKeyword().equals("CONTRACT")) {
System.out.println("Player has inputed contract.");
i++;
message2.setKeyword("310");
chan.writeAndFlush(message); // Tells the current client his turn is over
System.out.println("End of turn for player.");
for (Channel channel : channels) { // Loop to tell the next client it's his turn
if (y == i) {
message2.setKeyword("309");
channel.writeAndFlush(message);
System.out.println("Start of turn for player.");
}
y++;
}
isOk = true;
playerAnswer.clearKeyword();
}
} catch (Exception e) {
e.printStackTrace();
}
}
isOk = false;
}
}
Please excuse this big chunk of code.
But for some reason my sentence "304 Please input a contract:" sent via chan.writeAndFlush(message); is sent to another client (and not the first one as it should through the loop) !
Am I missing something?
What do you mean by "first one"? ChannelGroup is a Set and it makes no guarantee to maintain insertion order when being iterated.
I am creating a java application that interact with Twitter using the library Twitter4J.
I want to download 10 000 nodes from twitter, and then do the statistics on the graph created. The graph is initially saved in a dataset (.txt file).
I must also save enough ReTweet for each node (so I have to check their timeline).
Skipping the instantiation of twitter to perform queries, I have two problems and doubts:
1) How do I manage the problem that the Twitter API have a limited number of required into a slot 15 minutes?
I tried this:
public static RateLimitStatus getApplicationRateLimitStatus(Twitter twitter)
{
try {
Map<String ,RateLimitStatus> rateLimitStatus = twitter.getRateLimitStatus();
for (String endpoint : rateLimitStatus.keySet())
{
if (endpoint.equals("/application/rate_limit_status"))
return rateLimitStatus.get(endpoint);
}
} catch (TwitterException te)
{
te.printStackTrace();
System.out.println("Failed to get rate limit status: " + te.getMessage());
System.exit(-1);
}
return null;
}
public static void control(Twitter twitter)
{
RateLimitStatus app_rate_limit_st = null;
RateLimitStatus user_timeline_limit_st = null;
RateLimitStatus credentials_limit_st = null;
RateLimitStatus friends_list_limit_st = null;
RateLimitStatus followers_list_limit_st = null;
int ctr_req = 7;
try {
if ((app_rate_limit_st = MyRateLimit.getApplicationRateLimitStatus(twitter)).getRemaining() < ctr_req)
{
System.out.println("I'm waiting "+app_rate_limit_st.getSecondsUntilReset()+" seconds for Application Rate Limit, app request remaining: "+app_rate_limit_st.getRemaining());
Thread.sleep((long)app_rate_limit_st.getSecondsUntilReset()*1000);
System.out.println("I woke up!!!");
}
}catch(InterruptedException e) {e.printStackTrace();}
}
In this block of code I checked only requests ApplicationRequest type, but in my application I checked also required type FriendList, FollowersList, UserTimeline and Credentials.
By running my application, is raised that notification
I have exceeded the number of available applications, and can not understand why.
2)
Another problem is with which algorithm should proceed to download the nodes.
I thought about taking a popular node (has many friends and followers, and who interact much with each other).
I tried to take the node, on the friends, his followers, and then the friends and followers of the friends and the friends and followers of followers.
It's a clever technique? They would know better?
Thanks.
Just a thought on how you can workaround the rate limit problem -
Create multiple twitter oauth credentials, you can maintain a list/set of Twitter instance configured with each available credential, when you reach a rate limit for say id1, you can switch to use id2 to fetch records.
Instead of using getApplicationRateLimitStatus, check for functional rate limit status and make a switch, this would help you plan the switch based on available limit for that API.
--Adding code/comments below as per the review comments,
You can do something like below, for each request you can use a connector, in your case you may need to cache few information that can be used to make next call like sinceId and maxId.
You would need to create/register multiple twitter accounts and generate credentials for each of them. I had tried this approach to fasten up fetching information for about 1 M users and it was effective.
You can also cache some recurring information and save few hits to Twitter, like in a network of 10 people its possible to have some percentage of common users/followers so to lookup user information a previously fetched user can be skipped in next request.
getTweetConnector() method will ensure you get a connector that has reset its ratelimit.
Since you are fetching information through multiple API's you can batch up connectors for specific request such that API's with higher rateLimit can have more connectors.
public class TweetUserInfo {
private Set<Twitter> mTwitterConnectorsSet;
private BufferedReader mUserFileReader;
TweetUserInfo(){
mTwitterConnectorsSet = new HashSet<Twitter>();
}
private void initTweetConnectors(String inFile) {
BufferedReader br = null;
try {
String line = null;
String[] lines = new String[4];
int linesIndex = 0;
br = new BufferedReader(new FileReader(inFile));
while ((line = br.readLine()) != null) {
if (linesIndex == 4) {
createAndAddTwitterConnector(lines);
linesIndex = 0;
}
lines[linesIndex] = line;
++linesIndex;
}
if (linesIndex == 4) {
createAndAddTwitterConnector(lines);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null)br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
private void createAndAddTwitterConnector(String[] lines) {
ConfigurationBuilder twitterConfigBuilder = new ConfigurationBuilder();
twitterConfigBuilder.setDebugEnabled(true);
for (int i = 0; i < lines.length; ++i) {
String[] input = lines[i].split("=");
if (input[0].equalsIgnoreCase("consumerkey")) {
twitterConfigBuilder.setOAuthConsumerKey(input[1]);
}
if (input[0].equalsIgnoreCase("consumersecret")) {
twitterConfigBuilder.setOAuthConsumerSecret(input[1]);
}
if (input[0].equalsIgnoreCase("accesstoken")) {
twitterConfigBuilder.setOAuthAccessToken(input[1]);
}
if (input[0].equalsIgnoreCase("accesstokensecret")) {
twitterConfigBuilder.setOAuthAccessTokenSecret(input[1]);
}
}
Twitter twitter = new TwitterFactory(twitterConfigBuilder.build()).getInstance();
mTwitterConnectorsSet.add(twitter);
}
private Twitter getTweetConnector() {
for (Twitter tc : mTwitterConnectorsSet) {
try {
if (tc.getRateLimitStatus() != null) {
if (tc.getRateLimitStatus().containsKey("/users/lookup")) {
if (tc.getRateLimitStatus().get("/users/lookup") != null) {
System.out.println("tc - "+tc);
System.out.println("tc rate - "+tc.getRateLimitStatus().get("/users/lookup").getRemaining());
if (tc.getRateLimitStatus().get("/users/lookup").getRemaining() > 2) {
return tc;
}
}
}
}
} catch (TwitterException e) {
e.printStackTrace();
}
}
return null;
}
}
Hope this helps.
Note: I understand that the console is for debugging and games should use GUI. This is for testing/experience
I'm writing a game that runs at 60fps. Every update, I check to see if the user has entered a String command. If so, it gets passed through, but if not, null is paas through, and the null is ignored.
Scanner is out of the question, since hasNext(), the method used to see if there is data to read, can potentially block and causes problems.
I've tried using BufferedReader.ready(). Not only did I have problems (never returned true), but I've read that it's not recommended for a few reasons.
BufferedReader.available() always returned 0, which in the documentation, it state's that InputStream.available() will always return 0 unless overriden. Here is my attempt:
class Game {
public static void main(String[] args) {
InputReader reader = new InputReader(System.in);
int timePerLoop = 1000/30;
Game game = new Game();
while(true) {
long start = System.nanoTime();
game.update(reader.next());
long end = System.nanoTime();
long sleepTime = timePerLoop + ((start - end) / 10000000);
if(sleepTime > 0)
try {
Thread.sleep(sleepTime);
}catch(InterruptedException e) {
e.printStackTrace();
}
else
Thread.yield();
}
}
public void update(String command) {
if(commands != null) {
//handle command
}
//update game
}
}
InputReader.java
public class InputReader {
private InputStream in;
public InputReader(InputStream stream) {
in = stream;
}
public String next() {
String input = null;
try {
while(in.available > 0) {
if(input == null)
input = "";
input += (char) in.read();
}
}catch(IOException e) {
e.printStackTrace();
}
return input;
}
}
InputStream by itself has the same problem as above. I'm not completely sure what type the object stored in System.in, but using available() yields the same results.
I've tried using the reader() from System.console(), but console() returns null. I've read into the subject, and I am not confused why. This is not the way to do it.
The goal is to check the stream to see if it contains data to read, so I can read the data knowing it won't block.
I do not want to use a separate Thread to handle user input, so please don't recommend or ask why.
The input has to be from the console. No new sockets are to be created in the process. I have read a few topics about it, but none of them clearly states a solution. Is this possible?
As you have said yourself, a custom GUI or an additional thread is the correct way to do this. However in absence of that, have you tried using readLine() for example: String inputR = System.console().readLine();
Some alterations to main():
Replace: InputReader reader = new InputReader(System.in); with:
Console c = System.console();
Replace: game.update(reader.next());
with: game.update(c.readLine());
Edit: This thread could also be helpful: Java: How to get input from System.console()
I'm trying to run a process and do stuff with its input, output and error streams. The obvious way to do this is to use something like select(), but the only thing I can find in Java that does that is Selector.select(), which takes a Channel. It doesn't appear to be possible to get a Channel from an InputStream or OutputStream (FileStream has a getChannel() method but that doesn't help here)
So, instead I wrote some code to poll all the streams:
while( !out_eof || !err_eof )
{
while( out_str.available() )
{
if( (bytes = out_str.read(buf)) != -1 )
{
// Do something with output stream
}
else
out_eof = true;
}
while( err_str.available() )
{
if( (bytes = err_str.read(buf)) != -1 )
{
// Do something with error stream
}
else
err_eof = true;
}
sleep(100);
}
which works, except that it never terminates. When one of the streams reaches end of file, available() returns zero so read() isn't called and we never get the -1 return that would indicate EOF.
One solution would be a non-blocking way to detect EOF. I can't see one in the docs anywhere. Alternatively is there a better way of doing what I want to do?
I see this question here:
link text
and although it doesn't exactly do what I want, I can probably use that idea, of spawning separate threads for each stream, for the particular problem I have now. But surely that isn't the only way to do it? Surely there must be a way to read from multiple streams without using a thread for each?
As you said, the solution outlined in this Answer is the traditional way of reading both stdout and stderr from a Process. A thread-per-stream is the way to go, even though it is slightly annoying.
You will indeed have to go the route of spawning a Thread for each stream you want to monitor. If your use case allows for combining both stdout and stderr of the process in question you need only one thread, otherwise two are needed.
It took me quite some time to get it right in one of our projects where I have to launch an external process, take its output and do something with it while at the same time looking for errors and process termination and also being able to terminate it when the java app's user cancels the operation.
I created a rather simple class to encapsulate the watching part whose run() method looks something like this:
public void run() {
BufferedReader tStreamReader = null;
try {
while (externalCommand == null && !shouldHalt) {
logger.warning("ExtProcMonitor("
+ (watchStdErr ? "err" : "out")
+ ") Sleeping until external command is found");
Thread.sleep(500);
}
if (externalCommand == null) {
return;
}
tStreamReader =
new BufferedReader(new InputStreamReader(watchStdErr ? externalCommand.getErrorStream()
: externalCommand.getInputStream()));
String tLine;
while ((tLine = tStreamReader.readLine()) != null) {
logger.severe(tLine);
if (filter != null) {
if (filter.matches(tLine)) {
informFilterListeners(tLine);
return;
}
}
}
} catch (IOException e) {
logger.logExceptionMessage(e, "IOException stderr");
} catch (InterruptedException e) {
logger.logExceptionMessage(e, "InterruptedException waiting for external process");
} finally {
if (tStreamReader != null) {
try {
tStreamReader.close();
} catch (IOException e) {
// ignore
}
}
}
}
On the calling side it looks like this:
Thread tExtMonitorThread = new Thread(new Runnable() {
public void run() {
try {
while (externalCommand == null) {
getLogger().warning("Monitor: Sleeping until external command is found");
Thread.sleep(500);
if (isStopRequested()) {
getLogger()
.warning("Terminating external process on user request");
if (externalCommand != null) {
externalCommand.destroy();
}
return;
}
}
int tReturnCode = externalCommand.waitFor();
getLogger().warning("External command exited with code " + tReturnCode);
} catch (InterruptedException e) {
getLogger().logExceptionMessage(e, "Interrupted while waiting for external command to exit");
}
}
}, "ExtCommandWaiter");
ExternalProcessOutputHandlerThread tExtErrThread =
new ExternalProcessOutputHandlerThread("ExtCommandStdErr", getLogger(), true);
ExternalProcessOutputHandlerThread tExtOutThread =
new ExternalProcessOutputHandlerThread("ExtCommandStdOut", getLogger(), true);
tExtMonitorThread.start();
tExtOutThread.start();
tExtErrThread.start();
tExtErrThread.setFilter(new FilterFunctor() {
public boolean matches(Object o) {
String tLine = (String)o;
return tLine.indexOf("Error") > -1;
}
});
FilterListener tListener = new FilterListener() {
private boolean abortFlag = false;
public boolean shouldAbort() {
return abortFlag;
}
public void matched(String aLine) {
abortFlag = abortFlag || (aLine.indexOf("Error") > -1);
}
};
tExtErrThread.addFilterListener(tListener);
externalCommand = new ProcessBuilder(aCommand).start();
tExtErrThread.setProcess(externalCommand);
try {
tExtMonitorThread.join();
tExtErrThread.join();
tExtOutThread.join();
} catch (InterruptedException e) {
// when this happens try to bring the external process down
getLogger().severe("Aborted because auf InterruptedException.");
getLogger().severe("Killing external command...");
externalCommand.destroy();
getLogger().severe("External command killed.");
externalCommand = null;
return -42;
}
int tRetVal = tListener.shouldAbort() ? -44 : externalCommand.exitValue();
externalCommand = null;
try {
getLogger().warning("command exit code: " + tRetVal);
} catch (IllegalThreadStateException ex) {
getLogger().warning("command exit code: unknown");
}
return tRetVal;
Unfortunately I don't have to for a self-contained runnable example, but maybe this helps.
If I had to do it again I would have another look at using the Thread.interrupt() method instead of a self-made stop flag (mind to declare it volatile!), but I leave that for another time. :)