• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Bear Bibeault
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Junilu Lacar
  • Paul Clapham
  • Knute Snortum
Saloon Keepers:
  • Stephan van Hulst
  • Ron McLeod
  • Tim Moores
  • salvin francis
  • Carey Brown
Bartenders:
  • Tim Holloway
  • Frits Walraven
  • Vijitha Kumara

Threads and synchronisation  RSS feed

 
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First thread print and write list of goods . Second look inside of goods/objects and count their weight. But second thread didn't work.

First thread separately run good, more i tried make second thread like simple construction ( for example System.out.println("something") and then was ok.



 
 
Marshal
Posts: 63795
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I merged your stuff with the following thread. I hope that is okay by you.
 
Miroslaw Butajlo
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Miroslaw Butajlo wrote:First thread print and write list of goods . Second look inside of goods/objects and count their weight. But second thread didn't work.

First thread separately run good, more i tried make second thread like simple construction ( for example System.out.println("something") and then was ok.
Sorry I am writing on mobile phone and I can't  use format code




 
Campbell Ritchie
Marshal
Posts: 63795
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch

Please don't ask the same question twice; I have joined your two discussions together.
Please indent your code correctly; lines 21‑31 are a good example of the sort of indentation that will confuse its writer. You would do better to use a multiple catch, since the two Exception types are not supertypes or subtypes to each other.
Never use == true and == false. Both are poor style and error‑prone.
Not while (b == true) ...
Always while (b) ...
Not while b == false) ...
Always while (!b) ...
I can see some strange logic. Look at lines 11 and 14 (SecondThread), which appear to be a contradiction to each other. Work out whether you will ever enter that block. I also think there is a serious error is making a field (state) public and static when  it is not a global constant.
Look at FirstThread line 44. That is an infinite loop. Never close a Scanner reading from System.in, not even if Eclipse suggests it. What will that infinite loop do to the state of your program?
Why is the List in line 74 public? And why is it static? I am pretty sure both of those things are mistakes.
Why are you extending Thread?

I think you will have to sort out the logic of your app before you can get it to work in multiple Threads.
 
Miroslaw Butajlo
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why loop in line 44 in FirstThread is bad ?

When I run only FirstTheard program work correctly.

Campbell Ritchie wrote:Welcome to the Ranch

Please don't ask the same question twice; I have joined your two discussions together.
Please indent your code correctly; lines 21‑31 are a good example of the sort of indentation that will confuse its writer. You would do better to use a multiple catch, since the two Exception types are not supertypes or subtypes to each other.
Never use == true and == false. Both are poor style and error‑prone.
Not while (b == true) ...
Always while (b) ...
Not while b == false) ...
Always while (!b) ...
I can see some strange logic. Look at lines 11 and 14 (SecondThread), which appear to be a contradiction to each other. Work out whether you will ever enter that block. I also think there is a serious error is making a field (state) public and static when  it is not a global constant.
Look at FirstThread line 44. That is an infinite loop. Never close a Scanner reading from System.in, not even if Eclipse suggests it. What will that infinite loop do to the state of your program?
Why is the List in line 74 public? And why is it static? I am pretty sure both of those things are mistakes.
Why are you extending Thread?

I think you will have to sort out the logic of your app before you can get it to work in multiple Threads.

 
Campbell Ritchie
Marshal
Posts: 63795
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You might have quoted my post, but did you look at the questions in it?
 
Bartender
Posts: 20568
120
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote: Never close a Scanner reading from System.in, not even if Eclipse suggests it.



I wish you wouldn't keep telling people this. Unless you can point me to an official proclamation from Oracle, I'm going to consider this assertion as folklore. And potentially dangerous folklore at that.

When you invoke close() on a Scanner, per the JavaDocs, if the underlying stream implements Closeable, then the Scanner close() will invoke the stream's close(). But System.in is a direct implementation of InputStream, and the Javadocs for InputStream explicitly state that:

JavaDoc wrote:
public void close()
          throws IOException

Closes this input stream and releases any system resources associated with the stream.

The close method of InputStream does nothing.



Emphasis mine. In other words, it's safe to close System.in, because the close should be a no-operation.

On the other hand, failing to close other types of input can leave them in an uncertain state. So my own recommendation is always to close the Scanner so that the code will be universal.
 
Campbell Ritchie
Marshal
Posts: 63795
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
. . . and why does that code throw an IOException before I even try to put anything into System.in for read() to find? Yes, I know it says that InputStream#close() does nothing, but why can't I enter even one char? If it does nothing, how can it close the stream or release any resources? Is that documentation comment consistent with itself? I looked back for older versions and the Jva5 version was the oldest I found, and that says exactly the same.And if closing the input stream does nothing, why am I getting a no such element exception before I even tried to write my “nextLine”? It isn't the close() call causing the exception to be thrown, but one line later.
 
Miroslaw Butajlo
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I changed my code
and I noticed that second thread worked in the moment but to early





 
Tim Holloway
Bartender
Posts: 20568
120
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Miroslaw, I'm sorry if we're trampling over your question, but I have an issue here and we probably ought to split it out into its own thread, sell tickets and popcorn and let everyone enjoy the fight.

Your example is, alas, too long for me to analyse in the detail it deserves, but at the risk of asking a question you've already addressed, are you taking into account the fact that the Java Scanner class javadoc explicitly warns against possible effects in a multi-threaded environment?

Transitioning into Campbell's contention, but also related to Miroslaw's problem is that there exists in Computer Science a class of constructs known as lexical analyzers or sometimes as "tokenizers". Lexical analyzers pass over a stream of primitive tokens (usually characters) and attempt to form more abstract tokens (for example, strings and numbers) from them. A transformation process. Very mathematical.

Now lexical analyzers actually come in quite a few different forms, denoted by their awareness of the context of the input token under scam. There's a notation for such forms, much like the "O" notation for algorithm performance, except that in this case, the "L" notation indicates how far to the left and/or right of the current position under examination to look in order to determine context and thereby which set of lexical rules to apply. Lexers are often implements as finite-state machines (often driven by tables of rules), so context determines what rules to apply next.

This has consequences. For example, you cannot accurately return a number until you are certain you've processed all the digits in the number. In general you can only do that by looking ahead until you find something that isn't a number. If I remember my terminology properly, this is something that can be done by a LALR(1) parser (stands for look-ahead, left-to-right, 1 character). And this is one reason why you shouldn't simply abandon a scanner when you think you're done with it. The scanner may have consumed an unpredictable amount of input.

Of course another reason why you shouldn't simply abandon a Scanner is that it's not in accordance with Generally-Accepted Java Principles. Often, abandoning resources carries serious consequences. Leaked database connections, network sockets, unflushed buffers and, of course, the potential for carrying a whole lot of junk around in RAM until the internal data structures are finally freed by the garbage collector.

I suppose that sooner or later Campbell is going to force me to do some actual work, though instead of merely counter-pontificating. In other words find out exactly what is going wrong in his example. Although I note as I have before that treating System.in as a source of heterogeneous data is not what I'd expect common practice to be.

But before I get to that point, two things to consider:

1. System.in an InputStream, not one of the line-oriented inputstreams. That's because a lot of Unix utilities pipe binary data between themselves, not just text. So when attached to a Scanner, any significance given to end-of-line characters has to be done by the scanner, not the stream.

2. IOException is more than just for attempting to read a closed file. It's also for attempting to read past end of file and other unspecified conditions. So which type of IOException are you actually getting?


 
Campbell Ritchie
Marshal
Posts: 63795
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:. . . the Java Scanner class javadoc explicitly warns against possible effects in a multi-threaded environment?

I hadn't noticed that we are threading a Scanner. I have tried to make my utility class thread‑safe, and failed miserably. As you said, that is a recipe for disaster.

. . . And this is one reason why you shouldn't simply abandon a scanner when you think you're done with it. The scanner may have consumed an unpredictable amount of input. . . .

I don't think a Scanner consumes or buffers pending input, but it does consume its delimiters. And when that delimiter changes from whitespace NOS to line end, it can cause no end of confusion.

. . . . Often, abandoning resources carries serious consequences. Leaked database connections, network sockets, unflushed buffers and, of course, the potential for carrying a whole lot of junk around in RAM until the internal data structures are finally freed by the garbage collector.

If using System.in, I prefer to keep the Scanner rather than simply allowing it to go out of scope. I prefer to use one and one only, in a utility class. Of course, as you imply, a Scanner reading from everything else must be closed, preferably with try‑with‑resources.

. . . treating System.in as a source of heterogeneous data is not what I'd expect common practice to be. . . .

Fortunately, by the time people get beyond reading simple things from System.in, they learn other forms of input, and read things from files, databases etc instead.

1. System.in an InputStream, not one of the line-oriented inputstreams. . . . when attached to a Scanner, any significance given to end-of-line characters has to be done by the scanner, not the stream.

The Scanner has its own way to do that; you can change the delimiter, or use the notorious nextLine() method. As Winston implied ages ago, it would have been much better if they had supplied a tutorial to go with Scanner. It is scary that so many books say that nextLine() reads the next line.

2. IOException is more than just . . . which type of IOException are you actually getting?

Isn't IOException vague? You have to look carefully at the message to have any idea what has gone wrong. Other exceptions, like Null Pointer Exception, give you a hint from their name.
 
Tim Holloway
Bartender
Posts: 20568
120
Android Eclipse IDE Linux
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Insomnia is a wonderful thing. I did a test. And incidentally, creating/closing a Scanner is gilding the lily. You get the same results from simply closing System.in and then attempting to read.

I got suckered. System.in is not just an InputStream, it's a BufferedInputStream. And closing a BufferedInputStream will cause subsequent reads to fail.

The Scanner is not a simple generic tokenizer or it wouldn't have a nextLine() method at all. I've a strong suspicion that it or an extended version of it may be used as the lexical scanner for the Java compiler. The entire existence of a nextLine method only makes sense if you want to do something like discard everything after "//" on an input line. Also, the Oracle implementation isn't "pure" Java. It uses a "sun.misc" class internally.

Bottom line is that I would be very wary of using System.in after it had been used with a Scanner, since the scanner does not assumed a buffered inputstream and it does not re-seek in the event that it ate too much before being discarded. Properly, if it's going to be used on a partial inputstream, there should have been a detach method to ensure that resources are cleanly released and the input source is left in a known state and seek position. With the caveat that System.in can be attached to non-seekable data sources at the OS level, so that an actual re-seek could fail if it falls outside the buffers.

Eh, this is getting to be a mess. Bottom line is that Scanner is a bastard class that fails to attend to some of the semantics. It's actually cleaner to wrap the inputstream in a line-reader, read line(s) and build a scanner for each line. The class documentation does not guarantee what condition the underlying input will be left in regardless of whether it's closed or merely abandoned. Other than for the first case, subsequent requests will throw an InvalidStateException.

I still maintain that it's better to close the Scanner. But if you're going to run a scanner on just a slice of System.in, it would be appropriate to implement a class that ensures that what gets eaten by the scanner is a known quantity. And whose close() method doesn't close its underlying InputStream.
 
Campbell Ritchie
Marshal
Posts: 63795
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:Insomnia is a wonderful thing. I did a test. . . . .

. . . but I have been too busy today to reply to your post; please wait until tomorrow.
 
Campbell Ritchie
Marshal
Posts: 63795
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:. . . System.in is not just an InputStream, it's a BufferedInputStream. . . . .

Not on JShell it ain't

Sorry for not doing this earlier, but this is what happens if you start looking for an inheritance tree on JShell:-

jshell> Class<?> clazz = System.in.getClass();
clazz ==> class jdk.jshell.execution.Util$1

jshell> Deque <Class<?>> stack = new ArrayDeque<>();
stack ==> []

jshell> do
  ...> {
  ...>    stack.push(clazz);
  ...>    clazz = clazz.getSuperclass();
  ...> } while (clazz != null);

jshell> while (!stack.isEmpty())
  ...> {
  ...>    System.out.println(stack.pop().getName());
  ...> }
java.lang.Object
java.io.InputStream
jdk.jshell.execution.PipeInputStream
jdk.jshell.execution.Util$1

So JShell uses a different subtype of InputStream; I couldn't find any details of pipe input streams here, never mind that anonymous class. Fortunately pipe input stream appears in src.zip jdk.jshell/jdk/jshell/execution/PipeInputStream.java, and this is its no‑args read() and close() method:-. . . and I can close System.in:-

jshell> System.in.close()

// ... Code block with compiler error removed.               ^

jshell> System.in.read();
$13 ==> -1

jshell> Scanner s = new Scanner(System.in); s.next();
s ==> java.util.Scanner[delimiters=\p{javaWhitespace}+] ... \E][infinity string=\Q∞\E]
|  Exception java.util.NoSuchElementException
|        at Scanner.throwFor (Scanner.java:937)
|        at Scanner.next (Scanner.java:1478)
|        at (#15:1)

Doing the same sort of thing outwith JShell gives me a different tree:

java InheritanceTreeDemo
java.lang.Object
java.io.InputStream
java.io.FilterInputStream
java.io.BufferedInputStream

Exactly as Tim told us last week: this is BufferedInputStream's close() method; as Tim told us already, it throws an IOException if you try any of its methods; its superclass has a sort of intermediate behaviour according to FilterInputStream#close(). That differs from System.in on JShell, which returns −1 after closing.

Now, I am beginning to think there is something naughty about all these different behaviours of different input streams, and that they aren't well documented. Actually, in my opinion, some of the documentation from some of the earlier versions of Java® is nothing like as good as Java8+ documentation.

It would appear that the Scanner object is trying for input and catching the IOException and throwing the unchecked no such element exception instead. But let's have a look at what Scanner claims to do:-

JDK11 Scanner documentation wrote:The next() and hasNext() methods and their companion methods (such as nextInt() and hasNextInt()) first skip any input that matches the delimiter pattern, and then attempt to return the next token. Both hasNext() and next() methods may block waiting for further input. Whether a hasNext() method blocks has no connection to whether or not its associated next() method will block. The tokens() method may also block waiting for input.

The findInLine(), findWithinHorizon(), skip(), and findAll() methods operate independently of the delimiter pattern. These methods will attempt to match the specified pattern with no regard to delimiters in the input and thus can be used in special circumstances where delimiters are not relevant. These methods may block waiting for more input.

When a scanner throws an InputMismatchException, the scanner will not pass the token that caused the exception, so that it may be retrieved or skipped via some other method.

So, let's try retriveing the skipped token:-

jshell> Scanner s = new Scanner(System.in);
try
{
  System.out.println(s.nextInt() * 2);
}
catch (InputMismatchException ex)
{
  ex.printStackTrace(); System.out.println(s.next());
}
s ==> java.util.Scanner[delimiters=\p{javaWhitespace}+] ... \E][infinity string=\Q∞\E]
123
246

// same code
Campbell
java.util.InputMismatchException
at ...
Campbell

It would appear that a Scanner might retain things in its buffer if it is using the findXXX() methods or has thrown an input mismatch exception, but not otherwise. If you have lots of whitespace including line ends between successive tokens, that simply counts as delimiter. Once you reach something printable that counts as the next token but not until you push the enter key.
I agree, the semantics does look peculiar, but it does seem to work. Unfortunately, as Winston said ages ago, it hasn't got an intuitive interface, nor is it well documented.
 
Tim Holloway
Bartender
Posts: 20568
120
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I meditated on the Scanner class, and came to the conclusion that one should always close a Scanner after use. Irrespective of where the data comes from.

It's true that when you apply a Scanner to a non-file character source that it's probably not going to hang on to anything except maybe some internal buffers after you quit using it before being signalled with end-of-data. However, I figure it can't hurt to make the scanner dismantle itself and go into a state where unplanned later use would throw an InvalidStateException. It's theoretically possible that garbage collection might be slightly more efficient post-close as opposed to waiting until the entire Scanner is disposed of as a whole, for what that's worth.

For file stream input, I continue to maintain one should close the Scanner. However, if you do slice out a segment of the inputstream for scanning instead of consuming the the whole thing, I'd recommend creating a line-oriented Reader class to act as the actual Scanner input for the inputstream. That way you can feed the Scanner known data, and when the Scanner closes it, it can ensure that nothing from the underlying file (or other) stream is left dangling or lost but rather that the underlying stream's input cursor is in a guaranteed known position.

The Scanner class is sloppy, and yes, you can be sloppy and (generally) get away with it, but I recommend applying a more consistent and rigourous usage of it, even though slightly more work is required. That way you can smooth over its warts, resulting in more reliable and more generically usable code.
 
Campbell Ritchie
Marshal
Posts: 63795
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But you still would end up closing System.in. That is the one exception to the rule that Scanners should be closed.
 
Tim Holloway
Bartender
Posts: 20568
120
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:But you still would end up closing System.in. That is the one exception to the rule that Scanners should be closed.



No. The point of using a line-reader input acting over System.in is that the line-reader should not have its close() routine close the underlying inputstream (whether System.in or something else entirely). Because this is a class whose purpose is to present a series of text lines that is a subset of some larger input source. Any class that operates on a subset of a larger source of data would not be within rights to do rude things to that larger source, and that is, in fact, one of the reasons why I don't think a Scanner should do so either, whether it's to close System.in or leave System.in possibly aimed at a random character position. I'm positing an overlay that always consumes complete lines and never more lines than the Scanner would be expected to consume.

So this user-supplied line-Reader class has its close() routine called by the Scanner close(). The line-reader close() discards any unconsumed text from the last line it read, but does NOT invoke close() on the underlying stream. Because it's only operating on a subset of the inputstream, not on its totality.

Thus we kill 2 birds with one stone: allow close() to always be invoked on the Scanner, allow the underlying stream's cursor to end up at a known location (1st position of the next line after the last one read by the Scanner), and as a bonus, can be also used on other sources than the stock iostreams with consistent and predictable behavior.

I'm still dubious that many applications would use a Scanner on just part of the System.in stream being fed to them, but the approach I suggested makes it possible to do so safely and is no more kludgy than just dropping a processor without proper regard for stabilising its state.
 
Campbell Ritchie
Marshal
Posts: 63795
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That would be the ideal; as you said last week about a detach() method. You can't simply use close() because that has to close whichever resource it is associated with; if you have an input stream reading anything else, you do have to close that stream, so I can't at the moment envisage how you could make an exception for System.in.
The alternative approach is not to use System.in.
 
Tim Holloway
Bartender
Posts: 20568
120
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One final thought. The Streams and System classes were designed as part of the initial creation of the Java language and environment. While it's true that so was java.lang.Date , the concepts relating to stdin, stdout, and stderr were anything but novel to the designers - stdio is old or older than Unix itself (I recall something similar on IBM's mainframe OS's back in the early 1970's).  And in the 1990's Sun was one of the premier Unix plaftorms of the world. So it's highly unlikely that they assigned System.in to a Stream that could be closed accidentally - or left unaddressed these many years. It wouldn't have been difficult to give the BufferedInputStream a no-op close option or even make a special stdio Stream class. And this was done before Java development and support was offshored, so you can't even say it's something done by people hired more for cost-saving reasons than for actual expertise.

Which leads to the conclusion that they expected people to be able to close System.in and that perhaps your allergy to closing System.in is misplaced. In point of fact, I'm fairly certain that the whole Unix-style stdin mechanism was designed to do that and has been used to do various tricks, including assigning alternative inputstreams to sysin while the application is executing. And if my memory hadn't deteriorated, I might even think of cases where I'd exploited that myself in C or some other language(s). Maybe even in Java on some cases where Java launched an external Process whose stdio needed to interact with the launching app. In such cases, you might need to explicitly close the stdin stream so that you could open it on something else. Or hand it over to some other process.

In point of fact, stdin, stdout, and stderr are simply the first 3 filehandles for a system process, pre-opened to shell-assigned data streams (console, by default) and there's no magic that says you cannot do anything with them that you can with any other streamable data source or sync.

With that, I think we've probably worried the topic to death. I hope that somewhere along the way we've managed to help poor Miroslaw.
 
Time is the best teacher, but unfortunately, it kills all of its students - Robin Williams. tiny ad:
global solutions you can do in your home or backyard
https://coderanch.com/t/708587/global-solutions-home-backyard
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!