Setting up a CI-engine is akin to setting up a fire alarm in a house.
In my mind the benefits do not correlate with many developers, but with a large code base. The CI-engine actively do all the boring work you do not want to do yourself, and do it everytime.
If you break a remote module which you haven't touched for a long time, you are told immediately. Not only compilation wise, but also functionwise if you have set up unit tests.
Also note that if you let you CI-engine do all the boring work, including setting up installers etc, you do not have to do it manually. You can just check in your source, and await the finished product being built in the standard location. (EDIT: The CI-engine also works in a well-defined environment, avoiding any developer specific setups, ensuring reproducibility)
This is also a part of quality assurance.
EDIT: After writing the above, I have had experience with the Maven build tool for Java. Essentially this allows us to keep the complete CI-configuration inside the project (with pom.xml) making it much simpler to maintain the CI-installation and/or migrate to another CI-engine.
Is there any algorithm that must use one of them in its implementation?
Almost certainly not. (Indeed, from the theoretical perspective, you should be able to simulate wait / notify using other java.util.concurrent.. classes. And synchronized could be replaced with explicit Lock operations ... though you would need to be careful to unlock in finally
clauses.)
However, there are probably algorithms where the best performing implementation in Java involves direct use of synchronized, with or without wait and notify.
Is it time to deprecate synchronized, wait and notify?
Irrespective of the answer to the previous question, the answer is definitely no.
The wait / notify can be (and often are) used correctly. In Java, deprecation is reserved for classes and methods that are broken; i.e. where continued use should be corrected as a matter of urgency. If Sun (and now Oracle) deprecated something as fundamental and as widely used as wait/notify, they would be creating a serious compatibility problem for huge amounts of legacy code. That is NOT in anyone's interest.
If you want to get rid of synchronized / wait / notify in your code, that is fine. But deprecation calls for the rewriting of large amounts of essentially correct multi-threaded code, and that would be a BAD IDEA. Corporate IT managers and software product managers would hate you for suggesting it ...
It is worth reading what "deprecated" means according to the Java documentation: http://docs.oracle.com/javase/1.5.0/docs/guide/javadoc/deprecation/deprecation.html
And also note that we are talking about deprecating stuff that is core to the Java language. Deprecating synchronized
has huge consequences.
Best Answer
@Deprecated
annotation is the correct thing to do. Removing code creates breaking changes in the API that is being used - this can be bad.The thing is that often people ignore the 'bad' thing and still use deprecated methods because it doesn't fail the build. Thus, the next correct thing to do is to make using deprecated methods fail the build.
It is possible to make the build scripts often used by Java developers to fail the build on compiler warnings (not only errors). There are various approaches to doing this depending on the build system being used (gradle, maven, ant, ...).
At the point that you now fail the build when (unconsciously) using the deprecated method (you upgraded the library, something is now deprecated, the build fails - this is a good thing).
At that point, you can specifically disable deprecated warning for that method call with
@SuppressWarnings( "deprecation" )
and then it will build again. But now you know that you need to fix that code, because your build failed and that alerted you to the changing API.