读书笔记:Effective Java, Second Edition-1,10章

enum内部实现继承了Enum,所以它不能继承别的类,另外,enum也不能作为别的类的父类。

一 对象构造销毁

Item 1用静态方法代替构造器

优点:

不像构造器那样,静态工厂方法拥有名字,可以包含某些意义。

不像构造器那样,每次调用都要创建对象,静态方法可返回可不返回。构造器你要不返回那只有抛个异常了。

不像构造器那样,静态工厂方法可以返回类型的某个子类型。

静态工厂方法可以减少冗长的创建参数化类型时的代码【扯淡,现在还不支持类型推断】

缺点:

一个类在仅提供静态工厂方法,同时没有公共或受保护的构造器时,此类是没法被子类化的。不能很好的使用集成的便利

静态工厂方法和其他的静态方法没什么差别,用户很迷惑,到底是用构造器还是工厂?

Item 2当构造一个对象需要很多的参数时,建议使用builder方式

最终达到这样的效果:

NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).build();

链式调用以及最后的构建方法build产生对象。

Item 3强制单例类的构造器为不可见,或者使用enum来做单例。

Item 4像Utils这样的类也将他的构造器设为不可见,你懂的。

Item 5不要创建不必要的对象

注意节约资源,特别注意循环中的对象创建,注意封箱拆箱可能造成的问题

Item 6内存泄露

public Object pop() {
if (size == 0)
throw new EmptyStackException();
return elements[--size]; //这里应该Object result = elements[--size];elements[size] = null;
}

如果elements不消除的话,虽然减少了一个元素,它是他还在内存中

……

Item 7: 避免析构

二 对象通用方法

十 并发

Item 66: 同步访问多线程可修改数据

如果要同步,读写都需要,否则没什么用处

这样的代码因为没有考虑同步,造成

// Broken! - How long would you expect this program to run?
public class StopThread {
private static boolean stopRequested;
public static void main(String[] args)
throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!stopRequested) //编译器会优化为while (true),因为stopRequested没有同步
i++;
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}

Item 67: Avoid excessive synchronization

同步块内尽量少做事情,特别是不要包含外部代码(及你不知道它做什么的代码,也许这个代码正要使用你的锁对象或其他)

为性能以及设计考虑,尽量不要对你的类进行同步设计,而应该非同步设计,文档告知调用方来让调用方维护同步,例如1.5新加的stringbuilder就是基于这种考虑而取代stringbuffer。例外的情况是静态字段的修改,则要保证同步。因为调用方可以想办法保证一个对象同步,却不能保证一个静态字段的同步。

tip:

CopyOnWriteArrayList这个类是在写的时候其实写的是拷贝的,实际的列表项没有改变,当然“很贵”,我应该不会用它。

多核心同步的花费:

In a multicore world, the real cost of excessive synchronization is not the CPU time spent obtaining locks; it is the lost opportunities for parallelism and the delays imposed by the need to ensure that every core has a consistent view of memory

Item 68: Prefer executors and tasks to threads

1.5开始包含的Executor Framework,queue和异步

创建ExecutorService executor = Executors.newSingleThreadExecutor();
执行executor.execute(runnable);
关闭executor.shutdown();

立即关闭shutdownNow();

但是不要被关闭着两个方法迷惑了,shutdownNow它只是intterupt方法而已,

它试图终止线程的方法是通过调用Thread.interrupt()方法来实现的,但是大家知道,这种方法的作用有限,如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt()方法是无法中断当前的线程的。所以,ShutdownNow()并不代表线程池就一定立即就能退出,它可能必须要等待所有正在执行的任务都执行完成了才能退出。

ScheduledThreadPoolExecutor替代java.util.Timer

详见 http://www.iteye.com/topic/366591

总之原来的thread,timer之流在使用时都要考量一番。

Item 69: Prefer concurrency utilities to wait and notify

java.util.concurrent报提供了三个方面的并发"龙套"模块

Executor Framework,

concurrent collections; 并发性能比普通高

synchronizers:线程间协作,等待等CountDownLatch,Semaphore,CyclicBarrier

从名字可以看出,CountDownLatch是一个倒数计数的锁,

当倒数到0时触发事件,也就是开锁,其他人就可以进入了。
在一些应用场合中,需要等待某个条件达到要求后才能做后面的事情;同时当线程都完成后也会触发事件,以便进行后面的操作。

CountDownLatch最重要的方法是countDown()和await(),前者主要是倒数一次,后者是等待倒数到0,如果没有到达0,就只有阻塞等待了。

下面的例子简单的说明了CountDownLatch的使用方法,模拟了100米赛跑,10名选手已经准备就绪,只等裁判一声令下。当所有人都到达终点时,比赛结束。

package com.eyesmore.concurrent;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchDemo {
    private static final int PLAY_AMOUNT = 10;
    public static void main(String[] args) {
        /*
         * 比赛开始:只要裁判说开始,那么所有跑步选手就可以开始跑了
         * */
        CountDownLatch begin = new CountDownLatch(1);
        /*
         * 每个队员跑到末尾时,则报告一个到达,所有人员都到达时,则比赛结束
         * */
        CountDownLatch end = new CountDownLatch(PLAY_AMOUNT);
        Player[] plays = new Player[PLAY_AMOUNT];
        for(int i = 0;i<PLAY_AMOUNT;i++) {
            plays[i] = new Player(i+1,begin,end);
        }
        ExecutorService exe = Executors.newFixedThreadPool(PLAY_AMOUNT);
        for(Player p : plays) {//各就各位
            exe.execute(p);
        }
        System.out.println("比赛开始");
        begin.countDown();//宣布开始
        try {
            end.await();//等待结束
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("比赛结束");
        }
        //注意:此时main线程已经要结束了,但是exe线程如果不关闭是不会结束的
        exe.shutdown();
    }
}
class Player implements Runnable {
    private int id;
    private CountDownLatch begin;
    private CountDownLatch end;
    public Player(int id, CountDownLatch begin, CountDownLatch end) {
        super();
        this.id = id;
        this.begin = begin;
        this.end = end;
    }
    public void run() {
        try {
            begin.await();//必须等到裁判countdown到0的时候才开始
            Thread.sleep((long)(Math.random()*100));//模拟跑步需要的时间
            System.out.println("Play "+id+" has arrived. ");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            end.countDown();//向评委报告跑到终点了
        }
    }
}

在实际应用中,有时候需要多个线程同时工作以完成同一件事情,而且在完成过程中,往往会等待其他线程都完成某一阶段后再执行,等所有线程都到达某一个阶段后再统一执行。
比如有几个旅行团需要途经深圳、广州、韶关、长沙最后到达武汉。旅行团中有自驾游的,有徒步的,有乘坐旅游大巴的;这些旅行团同时出发,并且每到一个目的地,都要等待其他旅行团到达此地后再同时出发,直到都到达终点站武汉。

这时候CyclicBarrier就可以派上用场。CyclicBarrier最重要的属性就是参与者个数,另外最要方法是await()。当所有线程都调用了await()后,就表示这些线程都可以继续执行,否则就会等待。

package examples.ch06.example01;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestCyclicBarrier {
    // 徒步需要的时间: Shenzhen, Guangzhou, Shaoguan, Changsha, Wuhan
    private static int[] timeWalk = { 5, 8, 15, 15, 10 };
    // 自驾游
    private static int[] timeSelf = { 1, 3, 4, 4, 5 };
    // 旅游大巴
    private static int[] timeBus = { 2, 4, 6, 6, 7 };
    static String now() {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        return sdf.format(new Date()) + ": ";
    }
    static class Tour implements Runnable {
        private int[] times;
        private CyclicBarrier barrier;
        private String tourName;
        public Tour(CyclicBarrier barrier, String tourName, int[] times) {
            this.times = times;
            this.tourName = tourName;
            this.barrier = barrier;
        }
        public void run() {
            try {
                Thread.sleep(times[0] * 1000);
                System.out.println(now() + tourName + " Reached Shenzhen");
                barrier.await();
                Thread.sleep(times[1] * 1000);
                System.out.println(now() + tourName + " Reached Guangzhou");
                barrier.await();
                Thread.sleep(times[2] * 1000);
                System.out.println(now() + tourName + " Reached Shaoguan");
                barrier.await();
                Thread.sleep(times[3] * 1000);
                System.out.println(now() + tourName + " Reached Changsha");
                barrier.await();
                Thread.sleep(times[4] * 1000);
                System.out.println(now() + tourName + " Reached Wuhan");
                barrier.await();
            } catch (InterruptedException e) {
            } catch (BrokenBarrierException e) {
            }
        }
    }
    public static void main(String[] args) {
        // 三个旅行团
        CyclicBarrier barrier = new CyclicBarrier(3);
        ExecutorService exec = Executors.newFixedThreadPool(3);
        exec.submit(new Tour(barrier, "WalkTour", timeWalk));
        exec.submit(new Tour(barrier, "SelfTour", timeSelf));
        exec.submit(new Tour(barrier, "BusTour", timeBus));
        exec.shutdown();
    }
}

Semaphore 信号量,就是一个允许实现设置好的令牌。也许有1个,也许有10个或更多。
谁拿到令牌(acquire)就可以去执行了,如果没有令牌则需要等待。
执行完毕,一定要归还(release)令牌,否则令牌会被很快用光,别的线程就无法获得令牌而执行下去了。

请仔细体会里面关于仓库的处理,

1 是如何保证入库时,如果仓库满就等待,

2 出库时,如果仓库无货就等待的。

3 以及对仓库只有10个库位的处理。

4 对同步问题的处理。

import java.util.concurrent.Semaphore;
/**
* 老紫竹JAVA提高教程-信号量(Semaphore)的使用。<br>
* 生产者和消费者的例子,库存的管理。
*
* @author 老紫竹(java2000.net,laozizhu.com)
*/
public class TestSemaphore {
  public static void main(String[] args) {
    // 启动线程
    for (int i = 0; i <= 3; i++) {
      // 生产者
      new Thread(new Producer()).start();
      // 消费者
      new Thread(new Consumer()).start();
    }
  }
  // 仓库
  static Warehouse buffer = new Warehouse();
  // 生产者,负责增加
  static class Producer implements Runnable {
    static int num = 1;
    @Override
    public void run() {
      int n = num++;
      while (true) {
        try {
          buffer.put(n);
          System.out.println(">" + n);
          // 速度较快。休息10毫秒
          Thread.sleep(10);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }
  // 消费者,负责减少
  static class Consumer implements Runnable {
    @Override
    public void run() {
      while (true) {
        try {
          System.out.println("<" + buffer.take());
          // 速度较慢,休息1000毫秒
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }
  /**
   * 仓库
   *
   * @author 老紫竹(laozizhu.com)
   */
  static class Warehouse {
    // 非满锁
    final Semaphore notFull = new Semaphore(10);
    // 非空锁
    final Semaphore notEmpty = new Semaphore(0);
    // 核心锁
    final Semaphore mutex = new Semaphore(1);
    // 库存容量
    final Object[] items = new Object[10];
    int putptr, takeptr, count;
    /**
     * 把商品放入仓库.<br>
     *
     * @param x
     * @throws InterruptedException
     */
    public void put(Object x) throws InterruptedException {
      // 保证非满
      notFull.acquire();
      // 保证不冲突
      mutex.acquire();
      try {
        // 增加库存
        items[putptr] = x;
        if (++putptr == items.length)
          putptr = 0;
        ++count;
      } finally {
        // 退出核心区
        mutex.release();
        // 增加非空信号量,允许获取商品
        notEmpty.release();
      }
    }
    /**
     * 从仓库获取商品
     *
     * @return
     * @throws InterruptedException
     */
    public Object take() throws InterruptedException {
      // 保证非空
      notEmpty.acquire();
      // 核心区
      mutex.acquire();
      try {
        // 减少库存
        Object x = items[takeptr];
        if (++takeptr == items.length)
          takeptr = 0;
        --count;
        return x;
      } finally {
        // 退出核心区
        mutex.release();
        // 增加非满的信号量,允许加入商品
        notFull.release();
      }
    }
  }
}

几乎没必要使用wait和notify,notifyAll,他们像是同步的汇编语言,而synchronizers则是提供了上层架构的高级语言。

如果确实需要使用,则牢记同步块中的循环中调用例如:

synchronized (obj) { while (<condition does not hold>) obj.wait(); ... // Perform action appropriate to condition }//这是java doc里面的的范例。

为什么要这样写:

Always use the wait loop idiom to invoke the wait method; never invoke it outside of a loop. The loop serves to test the condition before and after waiting. Testing the condition before waiting and skipping the wait if the condition already holds are necessary to ensure liveness. If the condition already holds and the notify (or notifyAll) method has already been invoked before a thread waits, there is no guarantee that the thread will ever wake from the wait. Testing the condition after waiting and waiting again if the condition does not
hold are necessary to ensure safety. If the thread proceeds with the action when the condition does not hold, it can destroy the invariant guarded by the lock. There are several reasons a thread might wake up when the condition does not hold:

• Another thread could have obtained the lock and changed the guarded state between
the time a thread invoked notify and the time the waiting thread woke.
• Another thread could have invoked notify accidentally or maliciously when
the condition did not hold. Classes expose themselves to this sort of mischief
by waiting on publicly accessible objects. Any wait contained in a synchronized
method of a publicly accessible object is susceptible to this problem.
• The notifying thread could be overly “generous” in waking waiting threads.
For example, the notifying thread might invoke notifyAll even if only some
of the waiting threads have their condition satisfied.
• The waiting thread could (rarely) wake up in the absence of a notify. This is
known as a spurious wakeup [Posix, 11.4.3.6.1; JavaSE6].

并且notifyAll要比notify要好。

note:

计时用 System.nanoTime()

Item 70: Document thread safety 为你的同步的方法写好文档、注释

Item 71: Use lazy initialization judiciously 主要讨论了同步情况下的懒加载问题,一般还是建议不需要迟初始化,以免造成并发情况下多次初始化的问题。

Item 72: Don’t depend on the thread scheduler

不要使用Thread.yield,可用sleep代替它。不要使用优先级,这个功能在各虚拟机上表现不一样。yield和优先级都只是暗示,并不意味着虚拟机会执行它们的功能。

Item 73: Avoid thread groups 请用前面提到的线程池而不要使用线程组,线程组你可以忘记他们了,他们是不成功的实现。

Continue reading 读书笔记:Effective Java, Second Edition-1,10章

静态字段,classloader,web容器

http://hi.baidu.com/liangzhongbo1/blog/item/f2c3201ae4b7250c34fa41f6.html

类加载器与 Web 容器

对于运行在 Java EE™ 容器中的 Web 应用来说,类加载器的实现方式与一般的Java 应用有所不同[默认的是从父到子]。不同的 Web 容器的实现方式也会有所不同。以 Apache Tomcat 来说,每个 Web 应用都有一个对应的类加载器实例。该类加载器也使用代理模式,所不同的是它是首先尝试去加载某个类,如果找不到再代理给父类加载器。这与一般类加载器的顺序是相反的。这是 Java Servlet 规范中的推荐做法,其目的是使得 Web 应用自己的类的优先级高于 Web 容器提供的类。这种代理模式的一个例外是:Java 核心库的类是不在查找范围之内的。这也是为了保证 Java 核心库的类型安全。

绝大多数情况下,Web 应用的开发人员不需要考虑与类加载器相关的细节。下面给出几条简单的原则:

每个 Web 应用自己的 Java 类文件和使用的库的 jar 包,分别放在 WEB-INF/classes 和 WEB-INF/lib 目录下面。多个应用共享的 Java 类文件和 jar 包,分别放在 Web 容器指定的由所有 Web 应用共享的目录下面。当出现找不到类的错误时,检查当前类的类加载器和当前线程的上下文类加载器是否正确。

http://agapple.iteyeeye.com/blog/826661

容器

jboss(4.05)

tomcat(6.0.30)

jetty(7.1.20)

支持child/parent first设置(默认值)

Java2ClassLoadingCompliance=false

delegate=false

_parentLoaderPriority=false

过滤package配置

FilteredPacages

默认值: javax.servlet,org.apache.commons.logging

packageTriggers

默认配置:org.apache.commons.logging

systemClasses

默认配置:java.

javax.

org.xml.

org.w3c.

org.apache.commons.logging.

org.eclipse.jetty.continuation.

org.eclipse.jetty.jndi.

org.eclipse.jetty.plus.jaas.

org.eclipse.jetty.websocket.

org.eclipse.jetty.servlet.DefaultServlet.

特殊性

1. UseJBossWebLoader=false时,过滤packages才能生效

2. UseJBossWebLoader=true时,不支持过滤packages

3. jboss 5.0以后UseJBossWebLoader参数将不支持

1. 在执行child/parent判断之前,会委托system classloader装载系统class,比如jdk的lib库

1. 多了一个serverclass配置,如果是serverclass优先采用child first

2. systemclass默认的配置,多了javax,org.xml,org.w3c配置。

相关文档

svn url : http://anonsvn.jboss.org/repos/jbossas/tags/JBoss_4_0_5_GA_CP18

jboss社区classloader文档: http://community.jboss.org/wiki/ClassLoadingConfiguration

svn url : http://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk

官方classloader机制: http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html

svn url : http://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/tags/jetty-7.2.0.v20101020/

classloader 官方文档: http://docs.codehaus.org/display/JETTY/Classloading

静态字段

http://stackoverflow.com/questions/797964/what-is-the-exact-meaning-of-static-fields-in-java

Static doesn't quite mean "shared by all instances" - it means "not related to a particular instance at all". In other words, you could get at the static field in class A without ever creating any instances.

As for running two programs within the same JVM - it really depends on exactly what you mean by "running two programs". The static field is effectively associated with the class object, which is in turn associated with a classloader. So if these two programs use separate classloader instances, you'll have two independent static variables. If they both use the same classloader, then there'll only be one so they'll see each other's changes.

As for an alternative - there are various options. One is to pass the reference to the "shared" object to the constructor of each object you create which needs it. It will then need to store that reference for later. This can be a bit of a pain and suck up a bit more memory than a static approach, but it does make for easy testability.

这个不知出处,但根据java规范,静态字段是在类加载器加载类时初始化的,也证明了上面的说法。

一般的java程序,每次启动也是单独的classloader实例,所以即使同一个类的main方法同时执行多次,也不会互相干扰。

总结发言,静态字段虽然是依附于classloader,在web容器下每个app又是自己的classloader,客观来说不会存在互相影响的问题,但任然存在这个风险。所以能不用就不用,特别是是对于单例模式。

 

Continue reading 静态字段,classloader,web容器

it-e-05 Air floating displays

Todays display technologies form a field of huge interest as they are evolving with big steps while expanding the range of their applications following the demands of the market. Two new display technologies, which are still in development, impress us mostly for their concept and not so much for their display quality or their potential applications.
Fog Screen company suggests a screen created by a thick layer of fog, formed in between of two air surfaces of smooth flow. The FogScreen works very much like an ordinary screen in terms of projection properties. It can be used for both back and front projection. This kind of screens allow the projection of very impressive images, while the viewer can walk through the screen, walk directly into the images, and through them! The fog used is dry, so it doesn't make you wet even if you stay under the Fog Screen device for a long time. The fog is made of ordinary water with no chemicals whatsoever. The screen is supported by projectors with brightness of at least 3,000 ANSI Lumens and for the best result, a dark background is highly recommended.
The world premiere demonstration of FogScreen was at the Science Fair in Turku, Finland in October 2002, and its researchers are awarded for their discovery. Its first installations have already been made in museums in France and Finland and it has recently been produced to the U.S.A in the form of interactive screen.

A relevant technology is being developed by the "IO2 Technologies" company. Known by the name "Heliodisplay", this technology uses a device that displays on a bed of air above it. Nothing is added to the air so there is not any harmful gas or liquid emitted from the device, and nothing needs to be refilled. The device produces interactive images, which means it can be used as a "floating touch screen". In the course of developing the technology, Heliodisplays have been built that display images ranging from 5" to 42" and it is estimated that it can reach 150". Like the FogScreen, Heliodisplay is best viewed in dark backgrounds. Although Heliodisplay is plug-and-play compatible with most video sources (TV, DVD, computer, videogame, etc.) and anything can be projected on the FogScreen, both screen technologies are not meant to substitute computer or television screens. Their basic application fields include projections in board meetings and presentations, trade shows, museum, theme parks etc.

Continue reading it-e-05 Air floating displays

it-e-06 System Software

Software refers to computer programs. Programs are the instructions that tell the computer how to process data into the form you want. There are two kinds of software: system software and application software.
System software is a collection of programs that enables application software to run on a computer system's hardware devices, it is background software and includes programs that help the computer manage its own internal resources.
Application software is a specialized programs that enables the user to accomplish specific tasks. In this text, we mainly discuss system software.
System software consists of four kinds of programs: bootstrap loader, diagnostic routines,basic input-output system, and operating system. Among these four parts, the operating system is we most concerned with, whith helps manage computer resources. Most important operating systems are: Windows, Windows NT, OS/2, Macintosh, and Unix.
Windows

Windows gets its name because of its ability to run multiple applications at the same time, each in its own window. Windows offers graphical user interface (GUI), presents the user with graphic images of computer functions and data. It provides a standard mechanism for copying or moving information from one program to another. This mechanism, called the Clipboard, means that information created in one context is instantly reusable in another, you don't need to reenter information or work with clumsy data-transfer utilities. Windows also has DDE (dynamic data exchange) and OLE (object linking and embedding) functions. In DDE two or more applications can be linked. This way, data created in one application is automatically entered into the others. OLE, like DDE, links data between applications. Additionally, OLE allows the application receiving the data to directly access the application that created the data.
Windows NT

Windows NT is an operating system designed to run on a wide range of
powerful computers and microcomputers. It is a very sophisticated and powerful operation system. Developed by Microsoft, Windows NT is not considered a replacement for Windows.
[1]Rather, it is an advanced alternative designed for very powerful microcomputers and networks. Windows NT has two major advantages when compare to Windows:
Multiprocessing It is similar to multitasking except that the applications are run independently at the same time. For instance, you could be printing a word processing document and using a database management program at the same time. [2]With multitasking, the speed at which the document is printed is affected by the demands of the database management program. With multiprocessing, the demands of the database management program do not affect the printing of the document.Networking In many business environments, workers often use computer to communicate with one another and to share software using a network. This is made possible and controlled by special system software. Windows NT has network capabilities and security checks built into the operating system. This makes network installation and use relatively easy. OS/2 OS/2 stands for Operating System/2. It was developed jointly by IBM and Microsoft
Corporation. OS/2 has many similarities with Windows NT. It is designed for very powerful microcomputers and has several advanced features. Some of its advantages over Windows NT
include:
Minimum system configuration Like Windows NT, OS/2 requires significant memory
and hard disk space. However, OS/2 requires slightly less.
Windows application Like Windows NT, OS/2 does not have a large number of
application programs written especially for it. OS/2 can also run Windows programs, but it runs these programs slightly faster than Windows NT.
Common user interface Microcomputer application programs written specifically for
Windows NT, as well as for OS/2, have consistent graphics interfaces. Across applications, the user is provided with similar screen displays, menus, and operations. Additionally, OS/2 offers a consistent interface with mainframes, minicomputers, and microcomputers. Macintosh Operation System The Macintosh Software, which runs only on Macintosh computers, offers a high-quality graphical user interface and is very easy to use. Apple Macintosh System 7.5 designed for Apple computers using Motorola's PowerPC microprocessor, is a significant milestone for Apple. It is a very powerful operating system like Windows NT and OS/2. System 7.5 has  network capabilities and can read Windows and OS/2 files. It has several

advantages:
Ease of use The graphical user interface has made the Macintosh popular with many
newcomers to computing. This because it is easy to learn.
Quality graphics Macintosh has established a high standard for graphics processing. This is a principal reason why the Macintosh is popular for desktop publishing. Users are easily able to merge pictorial and text materials to produce nearly professional-looking newsletters, advertisements, and the like.

Consistent interfaces Macintosh applications have a consistent graphics interface. Across all applications, the user is provided with similar screen displays, menus, and operations. Multitasking Like Windows, Windows NT, and OS//2, the Macintosh System enables you to do multitasking. That is, several programs can run at the same time.
Communications between programs The Macintosh system allows applications programs
to share data and commands with other applications programs.
Unix

Unix was originally developed by AT&T for minicomputers and is very good for
multitasking. It is also good for networking between computers. Unix initially became popular in industry because for many years AT&T licensed the system to universities for a nominal fee. It is popular among engineers and technical people, with the arrival of very powerful microcomputers, Unix is becoming a larger player in the microcomputer world. Unix can be used with different types of computer systems, that is, it is a portable operating system. It is used with microcomputers,
minicomputers, mainframes, and supercomputers. The other operating systems are designed for microcomputers and are not nearly as portable. It also has the advantages of multitasking, multiprocessing, multiuser, and networking.

Continue reading it-e-06 System Software

mysql dump 乱码问题

将utf8编码的数据库使用mysqldump.exe来导出,得到的却是乱码

明明设置了--default-character-set=utf8 任然如此,网上搜了些文章,例如 http://blog.derjohng.com/2006/01/18/backup-mysql-utf8-data/

说的是改为--default-character-set=latin1,我试了一下,还是乱码。莫名其妙,想了想试试如下的命令

"D:\Program Files\MySQL\MySQL Server 5.5\bin\mysqldump.exe" --user=root --password=root --default-character-set=gbk --skip-opt --add-drop-table --set-charset --dump-date --result-file=data.sql test

这样导出的结果编码才是正确的。(注意不要丢掉--skip-opt 选项)

问题是解决了,我还是莫名其妙。

明明设置的是utf8,数据库my.ini里面默认也是utf8,哪里搞出个gbk来了?

看官方文档,有这么一句话:

http://dev.mysql.com/doc/refman/5.1/en/charset-configuration.html

when character_set_system differs from character_set_server or character_set_client, and you input characters manually (as database object identifiers, column values, or both), these may be displayed incorrectly in output from the client or the output itself may be formatted incorrectly. In such cases, starting the mysql client with --default-character-set=system_character_set—that is, setting the client character set to match the system character set—should fix the problem.

似乎是要匹配文件系统字符集,也就是你的操作系统字符集。

Continue reading mysql dump 乱码问题

it-e-07 embedded system

An "embedded system" is a special-purpose computer system, which is completely encapsulated by the device it controls. An embedded system has specific requirements and performs pre-defined tasks, unlike a general-purpose personal computer.
Characteristics

Two major areas of differences are cost and power consumption. Since many embedded systems are produced in the tens of thousands to millions of units range,reducing cost is a major concern. Embedded systems often use a (relatively) slow processor and small memory size to minimize costs. The slowness is not just clock's speed. The wholearchitecture of the computer is often intentionally simplified to lower costs. For example,embedded systems often use peripheralscontrolled by synchronous serial interfaces, which are ten to hundreds of times slower than comparable peripherals used in PCs. Programs on anembedded system often must run with real-time constraints with limited hardware resources:often there is no disk drive, operating system, keyboard or screen. A flash drive may replace rotating media, and a small keypad and LCD screen may be used instead of a PC's keyboard and screen. Firmwareis the name for software that is embedded in hardware devices, e.g. in one or more ROM Flash memory IC chips. Embedded systems are routinely expected to maintain 100% reliability while running continuously for long periods of time, sometimes measured in years.
Firmware is usually developed and tested to much stricter requirements than is general purposesoftware (which can usually be easily restarted if a problem occurs). In addition, because the embedded system may be outside the reach of humans (down an oil well borehole, launched intoouter space, etc.), embedded firmware must usually be able to self-restart even if some sort of catastrophic data corruption has taken place. This last feature often requires external hardware assistance such as a watchdog timer that can automatically restart the system in the event of a software failure.

Platform

There are many different CPU architectures used in embedded designs. This in contrast to the desktop computer market, which as of this writing (2003) is limited to just a few competing architectures, mainly the Intel/AMD x86, and the Apple/Motorola/IBM PowerPC, used in the Apple Macintosh. One common configuration for embedded systems is the system on a chip, an application-specific integrated circuit, for which the CPU was purchased as intellectual property to add to the IC's design.

Continue reading it-e-07 embedded system

读书笔记:Effective Java, Second Edition-5章

Item 23: Don’t use raw types in new code

带参数泛型提供了安全类型检查,自动类型转换的便利,提倡使用。

raw type指没有指明类型的如List

List<String> 是 List的子类 但不是 List<Object>的子类,ArrayList<Object>才是List<Object>的子类。

List.class,String[].class, and int.class 合法,但 List<String>.class and List<?>.class不合法。

instance操作符只能使用Raw Type  (o instanceof Set) √ , (o instanceof Set<?>) ×

Set<Object> is a parameterized type representing a set that can contain objects of  any type,

Set<?> is a wildcard type representing a set that can contain only  objects of some unknown type, 无法使用

Set is a raw type, which opts out of the generic type system.

The first two are safe and the last is not.

Term
Example

Parameterized type
List<String>

Actual type parameter
String

Generic type
List<E>

Formal type parameter
E

Unbounded wildcard type
List<?>

Raw type
List

Bounded type parameter
<E extends Number>

Recursive type bound
<T extends Comparable<T>>

Bounded wildcard type
List<? extends Number>

Generic method
static <E> List<E> asList(E[] a)

Type token
String.class


Item 24: Eliminate unchecked warnings

消灭warning……

Item 25: Prefer lists to arrays

数组是协变的,if Sub is a subtype of Super, then the array type Sub[] is a subtype of Super[].

如此相反的是:Generics, by contrast, are invariant: for any two distinct types Type1 and Type2, List<Type1> is neither a subtype nor a supertype of List<Type2>

泛型的类型更强

不能建立泛型数组,因为需要保证泛型的类型安全【略】

总体来说就是,数组和泛型结合的不是很好,如果你碰到这种情况,使用列表代替数组。

Item 26: Favor generic types

泛型数组的解决方案(泛型中不得不用到数组的情况):

1:字段类型是T[],使用Object数组转换

private E[] elements;

// The elements array will contain only E instances from push(E).
// This is sufficient to ensure type safety, but the runtime
// type of the array won't be E[]; it will always be Object[]!
@SuppressWarnings("unchecked")
public Stack() {
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}

2:字段类型是Object数组,每次取数组元素时转换

// Appropriate suppression of unchecked warning
public E pop() {
if (size==0)
throw new EmptyStackException();
// push requires elements to be of type E, so cast is correct
@SuppressWarnings("unchecked")

E result = (E) elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
}

Item 27: Favor generic methods

Item 28: Use bounded wildcards to increase API flexibility

PECS 原则:if a parameterized type represents a T producer, use <? extendsT>;if it represents a T consumer, use <? superT>.

// Wildcard type for parameter that serves as an E consumer
public void popAll(Collection<? super E> dst) {
while (!isEmpty())
dst.add(pop());
}

// Wildcard type for parameter that serves as an E producer
public void pushAll(Iterable<? extends E> src) {
for (E e : src)
push(e);
}

Item 29: Consider typesafe heterogeneous containers

容器里面多种类型的情况:

// Typesafe heterogeneous container pattern - implementation
public class Favorites {
private Map<Class<?>, Object> favorites = new HashMap<Class<?>, Object>(); //以Class<?>作为键达到多种类型的目的。注意Class<?>这个特殊的形式参照Item23.
public <T> void putFavorite(Class<T> type, T instance) {
if (type == null)
throw new NullPointerException("Type is null");
favorites.put(type, instance);
}
public <T> T getFavorite(Class<T> type) {
return type.cast(favorites.get(type));//将Object安全的转为了绑定类型

Continue reading 读书笔记:Effective Java, Second Edition-5章

Pagination


Total views.

© 2013 - 2019. All rights reserved.

Powered by Hydejack v6.6.1