Afaik: The optimal number of threads for data that is suitable for parallel processing is the number of cores - since each thread has (theoretically) a core of its own to run on. For CPUs that are capable of hyper-threading it is 2x the number of cores. Please Correct me if I am wrong.
It is far, far more complicated than that.
It depends what you are optimizing for. If your are optimizing for efficient (i.e. cost effective) use of the available hardware, then it is rarely optimal. If any of the threads need to wait for a significant period for any reason, then a one-to-one allocation of threads to physical cores results in underutilization of cores. If those cores could be used to something else (e.g. run someone elses programs!) then your use is suboptimal.
Even if you are optimizing solely for application speed, a one-to-one allocation is not necessarily the best strategy.
Each application + workload has a "sweet spot" in terms of the number of threads. This depends on the amount and nature of any internal contention, and the amount and nature of communication with external systems (file systems, networking, etc).
If you have a rigid one-thread-per-core rule, then you can have at most N threads on an N core system.
If that N is significantly less than the "sweet spot" number of threads, you may find that cores are idle a lot of the time.
Now for hyper-threading.
Hyperthreads potentially give you extra CPU cycles per clock cycle. However, they don't give you extra cycles in memory system. The performance characteristics of a hyperthread "virtual core" will be different to a physical core ... and for real-life applications the difference will be significant. Hence the your 2 x assumption is without basis.
My question is if the underlying OS (Linux, Winodws OSX) will automatically realize my "intention" and e.g. assigns each thread to a single core assuming I have e.g. 8 cores and accordingly 8 threads where each of them works on a "time consuming" task?
Not necessarily.
The OS has to take account of other things that are happening on the system. Other applications, the daemons etc that handle your desktop, the stuff that deal with file systems and networking protocols.
The OS (and JVM) will generally only react to the what has already happened in making scheduling decisions. Predicting future behaviour based on past behaviour (at this level) is not cost effective ... and modern OSes don't attempt to do it except at a very crude / heuristic level. Perfect (optimal) prediction is impossible, and even if you have perfect knowledge the scheduling problem is NP-hard.
In theory, an application programmer could design an optimal schedule. In practice, most applications are too complicated for this AND it is difficult to take account of the other "random" things that are happening on the system.
Or the other way around: Is it possible to assign threads to cores (especially in Java)?
There is no practical way to do this. (See the @ksmonkey123's Answer) Certainly, not portably.
And it is probably unlikely to work in Java anyway. Java has the addition problem that there are hidden threads doing things behind the back of the application (e.g. the garbage collector and finalizer threads), and Java memory management is harder to predict and harder to tune for.