JDK环境变量相关

Ubuntu下安装oracle版本的JDK的话,可以通过添加ppa,然后 apt-get install,非常方便,而且之后环境变量基本上已经配置好了。环境变量的配置在 /etc/profile.d/下有两个文件:jdk.csh和jdk.sh,里面配置了环境变量。

我们可以在终端中输入命令 $echo $PATH 来查看环境变量,看看是否有jre jdk之类的环境变量在里面。

由于Ubuntu下面往往可以安装多个版本的 jdk,比如openJdk(开源的版本),所以我们需要工具来设置默认的java。

相关命令:

update-alternatives --config java 可以配置默认的java版本,也就是jre版本
update-alternatives --config javac 这个当然就是用来配置默认的jdk版本了,以下只举例 java
update-alternatives --display java 显示当前链接目前指向,其实就是在终端输入java命令,其实是指向 /usr/bin/java,而 /usr/bin/java又指向了哪里呢?这个命令就会显示出来了。
sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk1.8.0_25 /bin/java 300 这个之后 update-alternatives --display java就会多出来一行了

一个显示轮班的js小工具

源代码:https://coding.net/u/baozhuwanglei/p/xiaoxiangmu/git/tree/master/lunban
没有任何服务器端的代码,就是js+html,所以反应速度很快.效果如下图:

没有使用 jQuery,因为觉得没有必要,毕竟只是个小东西.
兼容性有问题,IE8不能显示,其他版本的IE浏览器可能也有同样的问题.IE浏览器对 innerHTML的支持有问题.后来我使用 jQuery的 append,可还是出现同样的问题,IE8不能显示,而火狐和chrome浏览器都正常.

算法:
三班两倒,也就是上班12小时,休息24小时.
算法很简单,首先随便选取某天的上班开始时间作为一个参照点,以时间戳的形式,三班都有.

比如有 甲 乙 丙 三班
甲乙丙的参照点时间戳分别为 A B C
求 D时为甲乙丙哪一班上班?

算法为:分别判断
(D - A)%(36*60*60) < 12*60*60 成立为甲上班
(D - B)%(36*60*60) < 12*60*60 成立为乙上班
(D - C)%(36*60*60) < 12*60*60 成立为丙上班

具体算法的实现:

//根据日期计算
	function pb(date) {
		date = new Date(Date.parse(date.replace(/-/g, "/")));
		date = date.getTime();	//为毫秒
		date = date/1000;	//转换为秒
		
		//alert(date);
		//alert(Math.abs(date-sy)%129600);
		
		if (date-sy==0 || Math.abs(date-sy)%129600<43200) {
			return '宋彦洲 杨延军';
		} else if (date-zw==0 || Math.abs(date-zw)%129600<43200) {
			return '朱建英 王瑶苛';
		} else if (date-ww==0 || Math.abs(date-ww)%129600<43200) {
			return '王磊 王啸';
		}
	}

设计模式之命令模式

命令模式就是将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化; 对请求排队或记录请求日志,以及支持可撤销的操作。

在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

这是一个遥控器的例子
一个灯类,有开灯、关灯、昏暗灯光之类的方法。
一个接口命令类:定义了执行和撤销两个方法。
下面有四个类实现了命令接口,分别是:开灯命令、关灯命令、昏暗开灯命令、昏暗关灯命令。
一个遥控器类,在模式中叫做调度者,依赖命令接口,调用命令的方法。
客户类,上图没有画,初始化命令类,传入遥控器类,调用遥控器类相应方法。

代码:
Light.java:

package headfirst.command.undo;

public class Light {
	String location;
	int level;

	public Light(String location) {
		this.location = location;
	}

	public void on() {
		level = 100;
		System.out.println("Light is on");
	}

	public void off() {
		level = 0;
		System.out.println("Light is off");
	}

	public void dim(int level) {
		this.level = level;
		if (level == 0) {
			off();
		}
		else {
			System.out.println("Light is dimmed to " + level + "%");
		}
	}

	public int getLevel() {
		return level;
	}
}

命令接口 Command.java:

package headfirst.command.undo;

public interface Command {
	public void execute();
	public void undo();
}

开灯命令 LightOnCommand.java:

package headfirst.command.undo;

public class LightOnCommand implements Command {
	Light light;
 
	public LightOnCommand(Light light) {
		this.light = light;
	}
 
	public void execute() {
		light.on();
	}
 
	public void undo() {
		light.off();
	}
}

关灯命令 LightOffCommand.java:

package headfirst.command.undo;

public class LightOffCommand implements Command {
	Light light;
 
	public LightOffCommand(Light light) {
		this.light = light;
	}
 
	public void execute() {
		light.off();
	}
 
	public void undo() {
		light.on();
	}
}

昏暗开灯命令 DimmerLightOnCommand.java:

package headfirst.command.undo;

public class DimmerLightOnCommand implements Command {
	Light light;
	int prevLevel;

	public DimmerLightOnCommand(Light light) {
		this.light = light;
	}

	public void execute() {
		prevLevel = light.getLevel();
		light.dim(75);
	}

	public void undo() {
		light.dim(prevLevel);
	}
}

昏暗关灯 DimmerLightOffCommand.java:

package headfirst.command.undo;

public class DimmerLightOffCommand implements Command {
	Light light;
	int prevLevel;

	public DimmerLightOffCommand(Light light) {
		this.light = light;
		prevLevel = 100;
	}

	public void execute() {
		prevLevel = light.getLevel();
		light.off();
	}

	public void undo() {
		light.dim(prevLevel);
	}
}

空命令 NoCommand.java:

package headfirst.command.undo;

public class NoCommand implements Command {
	public void execute() { }
	public void undo() { }
}

遥控器 RemoteControlWithUndo.java:

package headfirst.command.undo;

import java.util.*;

//
// This is the invoker
//
public class RemoteControlWithUndo {
	Command[] onCommands;
	Command[] offCommands;
	Command undoCommand;
 
	public RemoteControlWithUndo() {
		onCommands = new Command[7];
		offCommands = new Command[7];
 
		Command noCommand = new NoCommand();
		for(int i=0;i<7;i++) {
			onCommands[i] = noCommand;
			offCommands[i] = noCommand;
		}
		undoCommand = noCommand;
	}
  
	public void setCommand(int slot, Command onCommand, Command offCommand) {
		onCommands[slot] = onCommand;
		offCommands[slot] = offCommand;
	}
 
	public void onButtonWasPushed(int slot) {
		onCommands[slot].execute();
		undoCommand = onCommands[slot];
	}
 
	public void offButtonWasPushed(int slot) {
		offCommands[slot].execute();
		undoCommand = offCommands[slot];
	}
 
	public void undoButtonWasPushed() {
		undoCommand.undo();
	}
  
	public String toString() {
		StringBuffer stringBuff = new StringBuffer();
		stringBuff.append("\n------ Remote Control -------\n");
		for (int i = 0; i < onCommands.length; i++) {
			stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName()
				+ "    " + offCommands[i].getClass().getName() + "\n");
		}
		stringBuff.append("[undo] " + undoCommand.getClass().getName() + "\n");
		return stringBuff.toString();
	}
}

入口类:

package headfirst.command.undo;

public class RemoteLoader {
 
	public static void main(String[] args) {
		RemoteControlWithUndo remoteControl = new RemoteControlWithUndo();
 
		Light livingRoomLight = new Light("Living Room");
 
		LightOnCommand livingRoomLightOn = 
				new LightOnCommand(livingRoomLight);
		LightOffCommand livingRoomLightOff = 
				new LightOffCommand(livingRoomLight);
 
		remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);
 
		remoteControl.onButtonWasPushed(0);
		remoteControl.offButtonWasPushed(0);
		System.out.println(remoteControl);
		remoteControl.undoButtonWasPushed();
		remoteControl.offButtonWasPushed(0);
		remoteControl.onButtonWasPushed(0);
		System.out.println(remoteControl);
		remoteControl.undoButtonWasPushed();

		CeilingFan ceilingFan = new CeilingFan("Living Room");
   
		CeilingFanMediumCommand ceilingFanMedium = 
				new CeilingFanMediumCommand(ceilingFan);
		CeilingFanHighCommand ceilingFanHigh = 
				new CeilingFanHighCommand(ceilingFan);
		CeilingFanOffCommand ceilingFanOff = 
				new CeilingFanOffCommand(ceilingFan);
  
		remoteControl.setCommand(0, ceilingFanMedium, ceilingFanOff);
		remoteControl.setCommand(1, ceilingFanHigh, ceilingFanOff);
   
		remoteControl.onButtonWasPushed(0);
		remoteControl.offButtonWasPushed(0);
		System.out.println(remoteControl);
		remoteControl.undoButtonWasPushed();
  
		remoteControl.onButtonWasPushed(1);
		System.out.println(remoteControl);
		remoteControl.undoButtonWasPushed();
	}
}

设计模式之单例模式

单例模式就是保证类只有一个实例,经典的实现如下:

package headfirst.singleton.classic;

// NOTE: This is not thread safe!

public class Singleton {
	private static Singleton uniqueInstance;
 
	// other useful instance variables here
 
	private Singleton() {}
 
	public static Singleton getInstance() {
		if (uniqueInstance == null) {
			uniqueInstance = new Singleton();
		}
		return uniqueInstance;
	}
 
	// other useful methods here
}

如上构造函数是私有的,也就是说在类的外面,不能使用 new 关键词来创建类的对象。类中有一个静态的 Singleton类型的成员变量,用来存储 getInstance()成员方法创建的类实例,成员方法中检测成员变量是否为null,如果为null就new一下赋值给成员变量。

但是这种方式有一个问题,就是在多线程的时候,还是有可能出现多个实例。我们可以使用 synchronized语句块来解决。
修改如下:

package headfirst.singleton.dcl;

//
// Danger!  This implementation of Singleton not
// guaranteed to work prior to Java 5
//

public class Singleton {
	private volatile static Singleton uniqueInstance;
 
	private Singleton() {}
 
	public static Singleton getInstance() {
		if (uniqueInstance == null) {
			synchronized (Singleton.class) {
				if (uniqueInstance == null) {
					uniqueInstance = new Singleton();
				}
			}
		}
		return uniqueInstance;
	}
}

相比在 getInstance()加入限定 synchronized,这种方式性能会更好。

后注:
上面代码你可能会看到volatile,如果没有volatile会怎么样呢?

在同步块的上面,有一个 uniqueInstance ==null的判断。
上面程序如果没有volatile的话,问题是没有同步的情况下读取共享变量uniqueInstance,并发的情况下对象的状态值有可能是过期无效的。要解决这个问题也很简单,把uniqueInstance声明为volatile类型。volatile有什么作用?

当一个域声明为volatile类型后,编译器与运行时会监视这个变量:它是共享的,而且对它的操作不会与其他的内存操作一起被重排序。volatile变量不会缓存在寄存器或缓存在对其他处理器隐藏的地方。所以,读一个volatile类型的变量时,总会返回由某一线程所写入的最新值。

加上 volatile之后,性能几乎和之前的没有差别。