Vous êtes sur la page 1sur 4

Note:

 Creating a method that behaves differently depending on the argument object that you
pass it is called the Strategy design pattern. The method contains the fixed part of the algorithm
to be performed, and the Strategy contains the part that varies. The Strategy is the object that
you pass in, and it contains code to be executed. Here, the Processor object is the Strategy, and
in main( ) you can see three different Strategies applied to the String s.

Each inner class can independently inherit from an implementation. Thus, the inner

class is not limited by whether the outer class is already inheriting from an

implementation.

Without the ability that inner classes provide to inherit—in effect—from more than one

concrete or abstract class, some design and programming problems would be intractable.

So one way to look at the inner class is as the rest of the solution of the multiple-inheritance

problem. Interfaces solve part of the problem, but inner classes effectively allow "multiple

implementation inheritance." That is, inner classes effectively allow you to inherit from more

than one non-interface.

Also, you never need to

write an exception specification saying that a method might throw a RuntimeException

(or any type inherited from RuntimeException), because they are unchecked exceptions.

Because they indicate bugs, you don’t usually catch a RuntimeException—it’s dealt with

automatically. If you were forced to check for RuntimeExceptions, your code could get too

messy. Even though you don’t typically catch RuntimeExceptions, in your own packages

you might choose to throw some of the RuntimeExceptions.

So the answer is: If a RuntimeException gets all the way out to main( ) without being

caught, printStackTrace( ) is called for that exception as the program exits.


Keep in mind that only exceptions of type RuntimeException (and subclasses) can be

ignored in your coding, since the compiler carefully enforces the handling of all checked

exceptions. The reasoning is that a RuntimeException represents a programming error,

which is:

This is different from

recovering a Serializable object, in which the object is constructed entirely from its stored

bits, with no constructor calls. With an Externalizable object, all the normal default

construction behavior occurs (including the initializations at the point of field definition),

and then readExternal( ) is called. You need to be aware of this—in particular, the fact that

all the default construction always takes place—to produce the correct behavior in your

Externalizable objects.

One way to prevent sensitive parts of your object from being serialized is to implement your

class as Externalizable, as shown previously. Then nothing is automatically serialized, and

you can explicitly serialize only the necessary parts inside writeExternal( ).

If you’re working with a Serializable object, however, all serialization happens

automatically. To control this, you can turn off serialization on a field-by-field basis using the

transient keyword, which says, "Don’t bother saving or restoring this—I’ll take care of it."

The problems that you solve with concurrency can be roughly classified as "speed" and

"design manageability."

One very straightforward way to implement concurrency is at the operating system level,

using processes. A process is a self-contained program running within its own address space.
A multitasking operating system can run more than one process (program) at a time by

periodically switching the CPU from one process to another, while making it look as if each

process is chugging along on its own. Processes are very attractive because the operating

system usually isolates one process from another so they cannot interfere with each other,

which makes programming with processes relatively easy. In contrast, concurrent systems

like the one used in Java share resources like memory and I/O, so the fundamental difficulty

in writing multithreaded programs is coordinating the use of these resources between

different thread-driven tasks, so that they cannot be accessed by more than one task at a

time

threading creates tasks within the single process represented by the executing

program. One advantage that this provided was operating system transparency, which was an

important design goal for Java.

Java’s

threading is preemptive, which means that a scheduling mechanism provides time slices for

each thread, periodically interrupting a thread and context switching to another thread so

that each one is given a reasonable amount of time to drive its task

Concurrent programming allows you to partition a program into separate, independently

running tasks. Using multithreading, each of these independent tasks (also called subtasks)

is driven by a thread of execution. A thread is a single sequential flow of control within a

process. A single process can thus have multiple concurrently executing tasks, but you

program as if each task has the CPU to itself. An underlying mechanism divides up the CPU

time for you, but in general, you don’t need to think about it.
Executors provide a layer of indirection between a client and the

execution of a task; instead of a client executing a task directly, an intermediate object

executes the task. Executors allow you to manage the execution of asynchronous tasks

without having to explicitly manage the lifecycle of threads. Executors are the preferred

method for starting tasks in Java SE5/6.

Although this book will use CachedThreadPools, consider using FixedThreadPools in

production code. A CachedThreadPool will generally create as many threads as it needs

during the execution of a program and then will stop creating new threads as it recycles the

old ones, so it’s a reasonable first choice as an Executor. Only if this approach causes

problems do you need to switch to a FixedThreadPool.

To clarify these discussions, I shall attempt to use the term "task" when I am describing the

work that is being done, and "thread" only when I am referring to the specific mechanism

that’s driving the task. Thus, if you are discussing a system at a conceptual level, you could

just use the term "task" without mentioning the driving mechanism at all.

It’s important to note that the increment operation itself requires multiple steps, and the task

can be suspended by the threading mechanism in the midst of an increment—that is,

increment is not an atomic operation in Java. So even a single increment isn’t safe to do

without protecting the task.

Vous aimerez peut-être aussi