Wednesday, April 20, 2016

Java 8 Multi-Threading in Practice

Dealing with multithreading and race conditions is a famously hard and tricky subject for computer science.  On top of that, Java has some odd and unexpected implementation details in this area as well.

The first thing I noticed is that my engine was taking over 40 seconds to shut down after a Ctrl-C.  Where was the interruption going?  It turns out that the forEach lambda, apparently as part of it's functionalness, completely ignores interruptions until it is completely done with its tasks.  This means that the new stream APIs are not useful for long-running tasks (e.g. the kinds of tasks you want to run in parallel in the first place) without a work-around, such as checking manually if a thread is interrupted or a thread pool is shutdown (see below).

The second thing I noticed that was when a Callable was being executed by and the executor service was shut down, the Callable's Thread.currentInstance().isInterrupted() would return false, even if actively checked!  As a work-around I had to pass a reference to the executor service into the Callable and check ExecutorService.isShutdown() instead.  In my particular code-base this caused a circular reference but the modern garbage collector uses mark-and-sweep instead of reference counting so no memory leaks happen.
It could be worse [1].
ExecutorService.invokeAll()

Lastly the APIs can't decide if they want Runnables or Callables.  ExecutorService.invokeAll() only takes Callables and ScheduledExecutorService.scheduleAtFixedRate() only takes Runnables.  Of course I have the same logic that sometimes needs to be run all at once and sometimes needs to be run repeatedly so I need to convert between the two.  It looks like if an exception does bubble out of a Runnable.run() call, it is simply ignored.  This caused some strange system behavior until I made a habit of catching Exception and logging an error.  Of course, we hate to catch Exception.  For this reason I strongly prefer Callable, despite the debate on StackOverflow.

The solution was to create a ThreadPool class and ScheduledThreadPool sub class in my project's utils module to simplify all of this complexity and automatically convert between Runnables and Callables as needed.  After I made these classes and had the code base use them it was easier to think about how the system worked instead of being mired in the details of the Java API.

[1] Dragon Riders of Pern by FanDragonBall

Wednesday, April 13, 2016

LocalDateTime Is Not Local!

No one ever has problems with Dates and Times!  (Y2k, 2038, 10,000)

Java8 dates and times were supposed to be a lot easier and designed by the Joda-Time guys.

One problem, after struggling for a full working day - LocalDateTimes are NOT Local!  Maybe in the sense of localized?  They are definitely UTC, not your local timezone.  Looking back at it, it says that it doesn't capture timezone information in the docs, but I didn't look at the docs because I thought that the name was blindingly obvious.

Copyright BBC
I was pulling my hair out when I wrote a function todayAt that returned a date that didn't register as today.  A time at 3:45 PM was being converted to 2 AM UTC (the next day) because LocalDateTime wasn't local.  I was looking for ZonedDateTime.

As they say, there are two hard things in Computer Science: caching, naming things and off by one errors.

Tuesday, April 5, 2016

What's the Goal of AI? Tai.ai and Bad Decisions

The implicit, if not explicit goal of artificial intelligence (AI) has been to create "human-like" intelligence.  The recent debacle of Tay.ai is the first time something has seemed to become strangely close.

That is to say, the aim of the project was to simulate someone in their late teens.  People in their late teens tend to make poor decisions, especially to go along with what people around them believe.  (I'm no exception and had quite a long "hippie phase" including being Vegan for 3 years.)
Vegan super-powers from Scott Pilgrim vs. the World


Do we really want to make an AI like us, with all of our foibles and cognitive distortions or are we going to pull the plug as soon as one adopts unconventional, minority or fringe views?  Will we use the phrase "it's just going through a phase"?

People do dumb stuff and usually learn from it and course correct... sometimes they make the same mistakes for decades on end until the very end.

I would think that if we are doing it right we will have a crop of AIs just as diverse as ourselves, including the bad stuff.

PS

I was in the hospital so missed a week or two of Tuesday posts.  It happens.

Tuesday, March 22, 2016

Spring Annotations: Using Constructor Arugments with @Autowired


Introduction

I've struggled for weeks with wanting to use a constructor with arguments along with Spring Annotations (in particular @Autowired) but most blog posts and tutorials say that this isn't possible or needs to use Spring Expressions.

Hypothesis

There has got to be some way to do this.  The alternative I have been using was to have an empty object autowired in and then manually run a bunch of setters to inject the required configuration.  This ends up being error prone and verbose to verify (e.g. every public method has to check that the required fields are not null).

Results

After searching the web for a long time I finally found that you CAN use multi-argument constructors if you refrain from using the @Component or @Service annotations and instead create the classes in a @Configuration class with @Bean annotations.  After creating a class (manually, with new) you can autowire it by using AutowireCapableBeanFactory.autowireBean(Object) method.

Conclusion

My code is a lot more readable and simple now, and let me find a few subtle bugs that did not turn up in the unit tests.  I ended up with complex object creation logic, but it is out in the @Configuration classes instead of inside of the core objects.  I am much happier with this situation.

Tuesday, March 8, 2016

Java Lambdas and Interrupted Exceptions

I couldn't figure out why my application was taking 40+ seconds to shut down.  It turned out that a long-running process was in a Lambda expression and was completely ignoring the owning thread being shut-down.  Changing the code to a foreach loop fixed the problem.

It looks like foreach loops are still useful in Java 8 after all.

Short post today - not feeling well.

Wednesday, March 2, 2016

Great for Karaoke: Hack Star

I was sick and overworked on Tuesday (who isn't!), so this slightly-late post it may be a bit off topic.

It's a parody, in the spirit of Weird Al or James@War, of Nickleback's Rockstar: Hack Star.

It isn't 100% polished, but it's been in my head since 2006!  If you look at the lyrics, it's roughly the 6 - 8th paragraphs.

We all want to be big hack stars,
With the Internet using all our Zips and WARs.
We'll have so many gadgets it'll be real neat,
No one will understand us cuz we'll all speak Leet.
And, we'll have the cash to live like Tzars,
hard work and talent will take you real darn far.
We'll have our competition ripping out their hair,
they'll complain to congress that it's just not fair,
and well,

Hay hay I want to be a hack star
Hay hay I want to be a hack star

We'll make apps so leet they'll augment your senses,
Me and my homies have our certs from Mensa.
I'll hack so hard that it takes up half my brain,
I'll hack so hard that drives me half insane.

Hay hay I want to be a hack star
Hay hay I want to be a hack star

Tuesday, February 23, 2016

Windows 10 for the First Time

Introduction

 Here's another Tuesday post!

I got a top-of-the-line new laptop (at Walmart...) that I've been delaying for far too long.  My four year old laptop barely runs ONE tab in Chrome.  I've had to revert to the old (original!  From 2006!) gmail settings a few times just to get anything done.

Original author unknown
In the same spirit as OSX for the First Time, here is Windows 10 for the First Time.

Background

As I mentioned before, I've been using MS-DOS / Windows for a long time and was fortunate enough to know enough to avoid Windows ME and Windows Vista.  It's been said that Microsoft gets every third product right (unknown attribution), so after Vista and Windows 8 I have moderate expectations for Windows 10.

First Day

The first day went pretty well.  The initial set-up process was really smooth, it connected to my WiFi and the internet just fine and there were not a whole bunch of updates to download right off of the bat.  I tried using YouTube with the new Edge Browser and it worked OK for the first half-hour, after that there were unforgivable errors (e.g. not being able to click inside of the video box).  I mean, who messes up Clicking these days!  I was not impressed.

Somewhere in there I asked "Cortana" how big my hard drive was... she sent me to Bing... I was, again, not impressed.  Also, it's just a text box.  No pretty face or anything!

Cortana from Halo - Copyright Microsoft
I downloaded Firefox at around the hour mark of "real usage" (e.g. not setup time).  Firefox was able to run video just fine on YouTube with no problems.

Second Day

Second day, I needed to print and scan with my networked printer (hp deskjet 2542 wireless all-in-one printer).  Printing worked great and the default drivers installed flawlessly and "just worked" for printing.  +1 to Microsoft, who is now shooting at 1 win and 2 losses.  Funny thing, the biggest hastle was figuring out how to bring up Notepad... I told Cortana to "Open Notepad" after futzing with the new Windows Button in the lower left and at least that worked.  I'll put that as 1 lose for the Windows Button and one win for Cortana, putting us at 2 wins and 3 losses.

Next up was scanning.  I had to install the custom HP software, which claims to be Windows 10 ready, in order to scan.  It kept being unable to setup the printer... which is already set up.  It said to uninstall the HP printer driver and restart the printer... and was then still unable to setup the printer.  Three hours later I booted up my Windows 8 dinosaur and scanned using that.  Epic fail for device drivers!  It was so frustrating it drove me to drink (a reasonable amount).  Windows 10 is now looking at 2 wins and 4 losses.

Conclusion

Avoid using Edge, peripherals and Cortana and it is working OK.  Microsoft usually has a long time frame in mind when releasing a new OS, so it's usually two years until a new OS is generally usable and Windows 10 looks to be no different.  Keep your old OS so that you can have working 3rd party device driver!  Final judgement 4.4 / 10, compared to the usual Microsoft products 8.0 / 10.

Why do I use Windows?  What's that phrase, devil you know?