What do you do for Singleton?

ajoo 2002-06-20 02:36:00
I see many programmers do singleton like:
class Singleton implements I{
static Singleton _inst = null;
static I getInstance(){if(_inst==null)_inst = new Singleton();return _inst}
}

Well, it works.
But, think hard. why wouldn't you do
class Singleton implements I{
static final Singleton _inst=new Singleton();
static I getInstance(){return _inst;}
}
?
Much simpler, right?

Many programmers would say: "the first one is lazy initialization. So should be better."

Really? by using the first one, what do you save? a Singleton object, right?

But how big is that? From my experience, a singleton is normally quite small. For a small object with 10-20 bytes, is it worthy the extra code "if(......)"?
the extra code will not use memory space anyway?
and it makes your code unnecessarily more complicated.

does it worth the extra runtime overhead to check the reference everytime the getInstance() is called?

Also, programmer often ignore the thread-safety of the first approach.

What if there are threads calling getInstance() concurrently? Do you need to place "synchronized" on your getInstance()?
And if you place "synchronized", you may also feel uncomfortable because even for non-concurrent usage of your Singleton, you are also paying the locking overhead for each call against getInstance(). Painful!

Of course, for big object, the lazy intialization is certainly useful. But, there's still another approach you may want to consider if the memory space for this big object is really something.

think about this: if every user of the singleton has finished using this singleton, do I still need to hold this object? Can I reclaim the memory space for it?

Then, you may want to use WeakReference to further optimize it.

for example:

class Singleton implements I{
static WeakReference _inst = null;
static I getInstance()
{
if(_inst==null || _inst.get()==null)
_inst = new WeakReference(new Singleton());
return (I)_inst.get();
}
}

It works?
Well, looks like. But no!
(I give this wrong demo to show that sometimes introducing more code is probably introducing more chances to get bug.)

You may just return "null" sometimes. This is because of the WeakReference! It does not guarantee to hold the new Singleton instance for you.

So, a possible version would be:
class Singleton implements I{
static WeakReference _inst = null;

static synchronized I getInstance()
{
I ret;
if(_inst==null){
ret = new Singleton();
_inst = new WeakReference(ret);
}
else
{
ret = (I)_inst.get();
if(ret == null){
ret = new Singleton();
_inst = new WeakReference(ret);
}
}
return ret;
}
}
quite something to do!
...全文
81 34 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
abcabcabc___ 2002-07-01
  • 打赏
  • 举报
回复
no, jls didnt say that way, for example, if you have a global varible x , which is used to flag certain condition or holding something, then currently, your only hope is x is no bigger than 32 bits. because volatile doesnt work properly.

BTW, immutable string can be changed make the whole immutable a joke.
ajoo 2002-07-01
  • 打赏
  • 举报
回复
ok. thank you for the link!
design patterns can easily go too abstract and phylosophical.
yakuu 2002-07-01
  • 打赏
  • 举报
回复
ok, our discussion should be over.
continued topic is far off.
but can we talk about the design patterns.
i can use 200 each topic.^_^
ajoo 2002-07-01
  • 打赏
  • 举报
回复
he he. imutable only when you do it immutably.

for example,

msg = new String(...);

see? msg's still mutable.

and the problem is because of the mutable assignment.
abcabcabc___ 2002-06-30
  • 打赏
  • 举报
回复
the worest thing is , it breaks and you dont know. the error may happen once in 10 days or produce a result 1% larger than the original. those errors are very very hard to discover. i have heard that a bank emploree put all the interest below 1 cent to his own account when develope the system and got several handred thousand in 2 years and no auditing found it. how much checking normal program can enjoy?

yakuu 2002-06-30
  • 打赏
  • 举报
回复
the volatile keyword in Java is certainly not worthless or taboo. In fact, it is sometimes crucial that you do use it.

Alas, the only truly useful answer is "don't use it". At least, don't rely on it for anything...
Basically, the language and VM specifications don't really make it clear/precise/etc. what should/shouldn't really be done in the presence of volatile and so many implementations of the JVM don't do anything if volatile is specified. Note that there are some folks actively working to solve this in time for the next release.

so, we still rely upon the double check code.
yakuu 2002-06-30
  • 打赏
  • 举报
回复
alas, yes, make sure the object is big enough.

mm...but how big? ^_^
ajoo 2002-06-30
  • 打赏
  • 举报
回复
at least the object size has to be big enough (not just 10 bytes, 20 bytes) to justify the runtime overhead and code complexity of lazy init or double check.
yakuu 2002-06-30
  • 打赏
  • 举报
回复
how to use it depend on yourself .

both ok. i think.

^_^
ajoo 2002-06-30
  • 打赏
  • 举报
回复
concurrent programming IS tricky by itself.
The problem with double check was not ever promised by the jls that it will work.
So, if any program using double check failed, it's the code's bug,(at most you can blame the jls is not clear or not good) just as many other bugs in concurrent code. They are normally hard to find in nature.
and how many programs are using double check? don't think it's quite useful in real. As the article said, "static init" is neat and good enough.


"volatile" may be used to fix the problem in double check in the future. But before the new jls is made and all the current impl supports that, we as programmers should just wisely avoid double check.

Again, strongly recommend using "static init". Easy! most efficient! robust!
ajoo 2002-06-30
  • 打赏
  • 举报
回复
it works only in the new proposal of "volatile" semantics.
Now, volatile does not help at all.


But, don't think many Java code is "bound to" break.
ajoo 2002-06-29
  • 打赏
  • 举报
回复
Shocked!
thought the double check works!

anyway, it proves my claim: never bother complex code if not necessary.


Thank you yakuu! It has been extremely helpful! Otherwise, I might use the double check in my future projects.
:)
yakuu 2002-06-29
  • 打赏
  • 举报
回复
the difference is keyword:volatile

^_^
yakuu 2002-06-29
  • 打赏
  • 举报
回复
the old code:

public class JGKSingleton {
private static JGKSingleton instance_;
private static Object syncObject_;
public static JGKSingleton getInstance() {
if (instance_ == null) {
synchronized(syncObject_) {
if (instance_ == null) {
instance_ = new JGKSingleton();
}
}
}
return instance_;
}
}

the new code:

public class JGKSingleton {
private static volatile JGKSingleton instance_;
private static Object syncObject_;
public static JGKSingleton getInstance() {
if (instance_ == null) {
synchronized(syncObject_) {
if (instance_ == null) {
instance_ = new JGKSingleton();
}
}
}
return instance_;
}
}
abcabcabc___ 2002-06-29
  • 打赏
  • 举报
回复
didnt know there's such a nasty problem in java's design.
anyone knows if the memory model fixed?
If not, then java on mp machines are broken. with immutable can be changed, your program are bond to break.
yakuu 2002-06-28
  • 打赏
  • 举报
回复
i think there is a good article:
http://www.javaworld.com/javaworld/jw-01-2001/jw-0112-singleton.html

let's read it.^_^
yakuu 2002-06-28
  • 打赏
  • 举报
回复
mm, first, the singleton code is like that:

package com.jgk.patterns.singleton;
public class JGKSingleton {
/* Here is the instance of the Singleton */
private static JGKSingleton instance_;
/* Need the following object to synchronize */
/* a block */
private static Object syncObject_;
/* Prevent direct access to the constructor
private JGKSingleton() {
super();
}
public static JGKSingleton getInstance() {
/* in a non-thread-safe version of a Singleton */
/* the following line could be executed, and the */
/* thread could be immediately swapped out */
if (instance_ == null) {
synchronized(syncObject_) {
if (instance_ == null) {
instance_ = new JGKSingleton();
}
}
}
return instance_;
}
}

in my mind, it's work fine.
hehe, but i suspect it since i saw this article:
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

maybe it's true.
i'll check it.
yakuu 2002-06-28
  • 打赏
  • 举报
回复
at first, the code of above is wrong.
code like that:
public static Singleton getInstance() {
/* in a non-thread-safe version of a Singleton */
/* the following line could be executed, and the */
/* thread could be immediately swapped out */
if (instance_ == null) {
synchronized(this) {
if (instance_ == null) {
instance_ = new Singleton();
}
}
}
return instance_;
}

in my mind, i think it's work fine.hehe, but i have seen an article:
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

take a look at it. maybe it's true.
ajoo 2002-06-28
  • 打赏
  • 举报
回复
but when the space used by your "if(...)lock()if(...)....." is more than the memory used by the singleton object, what do you use?

and, the complex code at least needs a "if(...)" everytime, slower.
yakuu 2002-06-28
  • 打赏
  • 举报
回复
i have seen these codes in a paper.
mm, talking about design patterns, but it's purpose is compare with c++.
i think both ok if we don't care about the memory.
but my prefer the complex codes.^_^
加载更多回复(14)
You're not alone. At any given moment, somewhere in the world someone struggles with the same software design problems you have. You know you don't want to reinvent the wheel (or worse, a flat tire), so you look to Design Patterns--the lessons learned by those who've faced the same problems. With Design Patterns, you get to take advantage of the best practices and experience of others, so that you can spend your time on... something else. Something more challenging. Something more complex. Something more fun. You want to learn about the patterns that matter--why to use them, when to use them, how to use them (and when NOT to use them). But you don't just want to see how patterns look in a book, you want to know how they look 'in the wild'. In their native environment. In other words, in real world applications. You also want to learn how patterns are used in the Java API, and how to exploit Java's built-in pattern support in your own code. You want to learn the real OO design principles and why everything your boss told you about inheritance might be wrong (and what to do instead). You want to learn how those principles will help the next time you're up a creek without a design paddle pattern. Most importantly, you want to learn the 'secret language' of Design Patterns so that you can hold your own with your co-worker (and impress cocktail party guests) when he casually mentions his stunningly clever use of Command, Facade, Proxy, and Factory in between sips of a martini. You'll easily counter with your deep understanding of why Singleton isn't as simple as it sounds, how the Factory is so often misunderstood, or on the real relationship between Decorator, Facade and Adapter. With Head First Design Patterns, you'll avoid the embarrassment of thinking Decorator is something from the 'Trading Spaces' show. Best of all, in a way that won't put you to sleep! We think your time is too important (and too short) to spend it struggling with academic texts. If you've read a Head First book, you know what to expect - a visually-rich format designed for the way your brain works. Using the latest research in neurobiology, cognitive science, and learning theory, Head First Design Patterns will load patterns into your brain in a way that sticks. In a way that lets you put them to work immediately. In a way that makes you better at solving software design problems, and better at speaking the language of patterns with others on your team.
Quality Code: Software Testing Principles, Practices, and Patterns Stephen Vance (Author) BOOK DETAILS Paperback: 256 pages Publisher: Addison-Wesley Professional (December 2013) Language: English ISBN-10: 0321832981 ISBN-13: 978-0321832986 BOOK DESCRIPTION Test-driven, test-first, and test-early development practices are helping thousands of software development organizations improve their software. Now, in Quality Code: Software Testing Principles, Practices, and Patterns, Stephen Vance builds on all that’s been learned about test-driven development, helping you achieve unprecedented levels of first-time quality. Using real-world code examples, this guide introduces patterns, principles, and more than two dozen detailed techniques for testing any software system more fully, effectively, and painlessly. Vance presents a conceptual framework to help you focus your efforts and design recommendations for improving testability across the software lifecycle, and also provides hands-on guidance to simplify testing of the full spectrum of code constructs. You’ll learn how to choose the best testing techniques for every situation, from the most common scenarios to threading. Two complete case studies put it all together, walking you through testing a brand-new Java application and an untested “legacy” JavaScript jQuery plugin. Whether you’re developing cutting-edge code for a new start-up, or maintaining an unruly old system, this guide will help you deliver exactly what you need: quality code. • Simplify unit testing of all your code—and improve integration and system testing • Delineate intent and implementation to promote more reliable and scalable testing • Overcome confusion and misunderstandings about the mechanics of writing tests • Test “side effects,” behavioral characteristics, and contextual constraints • Understand subtle interactions between design and testability—and make them work for, not against, you • Discover core principles that guide your key testing decisions • Explore testing getters/setters, string handling, encapsulation, override variations, visibility, singleton patterns, error conditions, and more • Reproduce and test complex race conditions deterministically TABLE OF CONTENTS Part I: Principles and Practices of Testing Chapter 1. Engineering, Craftsmanship, and First-Time Quality Chapter 2. Intent of Code Chapter 3. Where Do I Start? Chapter 4. Design and Testability Chapter 5. Testing Principles Part II: Testing and Testability Patterns Chapter 6. The Basics Chapter 7. String Handling Chapter 8. Encapsulation and Override Variations Chapter 9. Adjusting Visibility Chapter 10. Interlude: Revisiting Intent Chapter 11. Error Condition Verification Chapter 12. Use Existing Seams Chapter 13. Parallelism Part III: Worked Examples Chapter 14. Test-Driven Java Chapter 15. Legacy JavaScript
2048游戏源码 # 2048 This is a derivative and the iOS version of the game 2048. In the very unlikely case that you don't know what it is, you can check it out [here](https://github.com/gabrielecirulli/2048). Made just for fun! You can find it on the [App Store](https://itunes.apple.com/us/app/2048-and-more!/id848859070?ls=1&mt=8).

Screenshot

## AI An AI is added, thanks to [DJBen](https://github.com/DJBen)! Tap "Hint" to show hint (e.g. Move left/right/up/down); tap "Auto Run" to run AI automatically. Check it out in the `AI` branch. You can also check out [this demo video on YouTube](https://www.youtube.com/watch?v=GF0ANNPpF8E). Thanks to [ov3y](https://github.com/ov3y/2048-AI)'s Javascript version that gave me (DJBen, that is) inspiration. ### Issues and pending improvements Currently the searching depth is 2 and it fails sometimes. You can increase the number to 3 or more by changing the return value of `- (NSInteger)maximumSearchingDepth` in `M2GlobalState+AI.h`. Ideally, the AI should search from 0 depth to infinity and have a time out, it records the current best move when finish searching the current depth and stops immediately when timed out and return the best move so far. However, I have a little bit of trouble when dealing with `NSOperationQueue` so I didn't do it this way. Now the AI only searches at the specified `-maximumSearchingDepth`. ## The Game Since it is a *derivative* of the original 2048, it is not the *same*. More explicitly, it has the following additions: * **Three board sizes**: 3x3, 4x4 and 5x5. The smaller the board is, the fewer cells you have, and the harder the game is.* * **Three game modes**: The original Power of 2, i.e. combining two tiles of the same value to produce their sum. The Power of 3, i.e. combining *three* consecutive tiles of the same value to produce their sum. Not surprisingly, this is pretty hard with the 3x3 board, although I found it pretty easy to get 81. 243 is a different story... And the Fibonacci sequence, i.e. combining two adjacent numbers in the sequence 2, 3, 5, 8, 13... (I omitted the two 1's in the beginning) to produce the one next to the larger value. This is pretty tricky. Try it out and you will know what I mean. * **Three themes**: I made a bright theme and a 'joyful' theme in addition to the original one. In case you wonder how to do themes in iOS. (There may be a better way, but themes are verbose in nature, because you *have to* specify all the colors, fonts, etc.) ## The Technology This version of 2048 is built using SpriteKit, the new 2-D game engine Apple introduced to iOS 7. As a result, it requires iOS 7 to run. On the other hand, this app has the following two great properties: * It does not rely on *any* third-party library. Not that Cocos-2D is not great, but the fact it's using SpriteKit means that it does not have any dependencies. * It does not have any images. That's right. The entire UI is done either via UIKit, or by Core Graphics. Check out the related files to see how that is done, if you are curious. You should be able to download the source, and build and run without problem. However, please note that you may not want to run it in the simulator unless you don't have an Apple Developer account. SpriteKit does use OpenGL, and simulating that using CPU will cause your computer to take off. ## The Code First off, the best thing about the code is that it's pretty well documented. Most methods have the Apple-style documentation, which means that you can triple-click on the method name to get its documentation. The code started to resemble the structure of the original 2048. So for example, it has a game manager, a board class, a tile class, etc. I at least *tried* to stick to MVC as much as possible. Here is a brief summary to get you started: * The `M2GameManager` class controls the game logic. There is only one action in the game: move. So the majority of that class is handling the move. The rest is checking whether you've won or died, etc. * The `M2Grid` class is the data structure for the board. The original 2048 used a 1-D array, but heck, 2-D array doesn't seem to be too bad here! ...except looping it is a bit ugly, so I made a `forEach` helper function. * The `M2Cell` class is the "slot"s. They are not the tiles themselves. The benefit of having this class is that the cells never move, so they are good references and they don't mess stuff up. * The `M2Tile` class is the actual tile, and **this** is the actual SpriteKit class. If all you want is some sample code for SpriteKit, here it is. I believe my animations are smoother than the other 2048 on the App Store, and are closer to the original animation. * The `M2GlobalState` class is a global class accessible from anywhere in the universe. Well, global stuff is evil, right? At least so we are told. But, it is at least better to encapsulate the global stuff into one single object (namespace), and that's a singleton right there. * The `M2Theme` class and its subclasses control the theme. * There are also some controller classes and view classes. It's probably a better idea to do the Game Over scene in SpriteKit, but I was lazy so I faked it using a view. The `M2GridView` class is the one that draws the board, btw. ### Contributing If you'd like to contribute, great! That's more than welcome. If you do make improvements to it, remember to put yourself in the "About 2048" page to get yourself credit. If you'd like to fork and make your own version, that's also great! Feel free to tinker with it however you'd like. It may not be a terribly good idea to change the font, add some ads, and submit to Apple, though. #### Contributors * Danqing Liu (me) * [Scott Matthewman](https://github.com/scottmatthewman) * [Sihao Lu](https://github.com/DJBen) ## Licence and Other 2048 for iOS is licenced under the MIT license. If you find the source code somewhat useful, all I ask is to download it from the [App Store](https://itunes.apple.com/us/app/2048-and-more!/id848859070?ls=1&mt=8), so I know that *someone* has seen it. Relax: It is free; it does not have any ads or weird stuff; it does not send you push notifications to ask you to go back and play it. You may also consider to [donate](https://github.com/gabrielecirulli/2048) to the maker of the original 2048 if you'd like, of course. (:

62,630

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧