log4j通常要配置属性,可以格式化输出内容
如:log4j.appender.stdout.layout.ConversionPattern=%c %d{ABSOLUTE} %5p %c{1}:%L - %m%n
com.***.utils.log4j.loogerTest 11:10:21 DEBUG "hello,world"
@SessionAttrbutes("user") 保存ModelView里面map的user对象
对应方法为:
public String ***(@ModelAttribute("abc") User user,ModelMap model)
public String ***(@ModelAttribute("abc") User user,ModelMap model)
public String ***( User user,ModelMap model)
java.util.concurrent
可重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。
在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁
非原子操作i++ 实则是由以下语句组成: before = i; i=before+1;
在多线程并发的情况下 如:i=98; thread a执行i++,线程b也执行i++,结果却有可能是99
线程a 线程b
before = 98 before = 98;
i=before+1=99; i=before+1=99;
线程ab都执行完i++了,却只加了1,
AtomicInteger实现的原子操作
//条件机制
当条件不满足时候,常见:
while(!condtion){
} // 占据了cpu,,采取sleep的话精确度不高
采取通知机制:
....
condtion.await(); //释放锁,并挂起当前线程
/////
otherThread->???(){
/////***********/
condtion.notify();
//////*********/
}
自旋锁是采用让当前线程不断地在循环体内执行实现的,当循环的条件被其他线程改变才能进入临界区
public class SpinLock {
private AtomicReference<Thread> sign =new AtomicReference<>();
public void lock(){
Thread current = Thread.currentThread();
while(!sign.compareAndSet(null, current)){ //不可重入,当同一个线程第二次调用lock时候,导致
//一直执行死循环,产生死锁
}
}
public void unlock (){
Thread current = Thread.currentThread();
sign.compareAndSet(current, null);
}
}
当第二个线程调用lock时候,由于不为null,所以一直循环等待
由于自旋锁只是将当前线程不停地执行循环体,不进行线程状态的改变,
所以响应速度更快。但当线程数不停增加时,性能下降明显,
因为每个线程都需要执行,占用CPU时间。
如果线程竞争不激烈,并且保持锁的时间段。适合使用自旋锁。
http://ifeve.com/java_lock_see4/ //good
https://www.cnblogs.com/qifengshi/p/6831055.html
http://ifeve.com/java-synchronousqueue/
ArrayBlockingQueue 数组阻塞队列,自然有数组特点,队列长度不可改变
LinkedBlockingQueue 链表阻塞队列,无界
SynchronousQueue 同步队列,生产一个,消费一个,
他是一个无界非缓存的队列,准确说他不存储元素,放入的元素,只有等待取走元素之后才能放入。也就是说任意时刻:
isEmpty()法永远返回是true
remainingCapacity() 方法永远返回是0
remove()和removeAll() 方法永远返回是false
iterator()方法永远返回空
peek()方法永远返回null
如线程池里面的,每来一个请求就添加一个线程,
add方法在添加元素的时候,若超出了度列的长度会直接抛出异常:
put方法,若向队尾添加元素的时候发现队列已经满了会发生阻塞一直等待空间,以加入元素。
offer方法在添加元素时,如果发现队列已满无法添加的话,会直接返回false。//poll则返回null
condition 必须在lock.lock(); lock.unlock();方法内调用
http://dongxuan.iteye.com/blog/901689
http://blog.csdn.net/java2000_wl/article/details/22097059
http://blog.csdn.net/ghost_Programmer/article/details/51620718
http://blog.csdn.net/ghost_programmer ///////////////////////////very ????
https://www.cnblogs.com/nullzx/archive/2016/02/14/5188890.html
oopyOnwrite容器即写时复制容器,当我们往一个容器添加元素的时候,
不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,
然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。
这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,
因为当前容器不会添加任何元素。
所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。
//适用于读多写少的情况,并发读取
copyOnwrite得到的数据并不是最新的,因为是new 一个数组之后,对新的数组
加锁实现修改操作,而之前的读线程仍然指向旧的引用,只有当遍历完数组后,数组的引用为0
了,这时候就会调用gc机制,在此之前,oldArray和newArray是同时存在的,所以内存为100*2=200M
yield方法使当前线程让出CPU占有权,但让出的时间是不可设定的。
yield()也不会释放锁标志。
实际上,yield()方法对应了如下操作;
先检测当前是否有相同优先级的线程处于同可运行状态,
如有,则把CPU的占有权交给次线程,否则继续运行原来的线程,
所以yield()方法称为“退让”,它把运行机会让给了同等级的其他线程。
yield()只是使当前线程重新回到可执行状态,所有执行yield()的线程有可能在进入到可执行状态后马上又被执行,
所以yield()方法只能使同优先级的线程有执行的机会
http://blog.csdn.net/canot/article/details/51087772
没有任何语言方面的需求要求一个被中断的程序应该终止。
中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断
如当线程sleep时候,抛出中断信号,线程接收到中断信号,从sleep状态重新变成可执行状态,之后根据条件
判断是否终止线程
你调用了Thread.sleep(10000), 预期线程睡10秒之后自己醒来,
但是如果这个特定条件提前到来的话, 来通知一个处于Sleep的线程。
中断是通过调用Thread.interrupt()方法来做的. 这个方法通过修改了
被调用线程的中断状态来告知那个线程, 说它被中断了. 对于非阻塞中的线程, 只是
改变了中断状态, 即Thread.isInterrupted()将返回true; 对于可取消的阻塞状态中的线程,
比如等待在这些函数上的线程, Thread.sleep(), Object.wait(), Thread.join(),
这个线程收到中断信号后, 会抛出InterruptedException
while (!stop) {
System.out.println("Thread running...");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
// 接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态
System.out.println("Thread interrupted...");
}
}
finnally{
// lock.release();
// cleanup();
//执行释放锁,清理资源等操作
}
// stop=true 此时线程要sleep20000后才能退出循环
// stop = true; thread.interrupt(); 接收到中断异常,之后执行while(!stop)退出循环
while(!Thread.currentThread().isInterrupted()&& more work to do){
// do more work;
}
Volley,OkHttp以及Retrofit
http://www.androidchina.net/3749.html //restful api设计
RESTful设计思想的提出者Fielding认为:
URI当中不应当出现动词,因为”资源“表示一种实体,所以应该用名词表示,而动词则应该放在HTTP协议当中。那么举个最简单的例子:
xxx.com/api/createUser
xxx.com/api/getUser
xxx.com/api/updateUser
xxx.com/api/deleteUser
这样的API风格我们应该很熟悉,但如果要遵循RESTful的设计思想,那么它们就应该变为类似下面这样:
[POST]xxx.com/api/User
[GET] xxx.com/api/User
[PUT]xxx.com/api/User
[DELETE]xxx.com/api/User
也就是说:因为这四个API都是访问服务器的USER表,所以在RESTful里URL是相同的,而是通过HTTP不同的RequestMethod来区分增删改查的行为。
而有的时候,如果某个API的行为不好用请求方法描述呢?比如说,A向B转账500元。那么,可能会出现如下设计:
POST /accounts/1/transfer/500/to/2
在RESTful的理念里,如果某些动作是HTTP动词表示不了的,你就应该把动作做成一种资源。可以像下面这样使用它:
POST /transaction HTTP/1.1
Host: 127.0.0.1
from=1&to=2&amount=500.00
对于基本数据类型来说,是进行“传值”传递。
而对于对象来说,与其说是“传引用”,更准确来说,不如说是在传“引用所指向的对象在堆当中的内存地址”。
而所谓的地址实际上也一串二进制数字。这也就是为什么网上有关于这个问题得出的结论
是“Java只有一种参数传递方式,那就是传值传递”的原因了。
java 基本类型 直接传值,object类型传内存地址
p1=p2 ; //将p1的指针指向p2
Java设计模式(1)工厂模式(Factory模式)
Java设计模式(2)单态模式(Singleton模式)
Java设计模式(3)建造者模式(Builder模式)
Java设计模式(4)原型模式(Prototype模式)
Java设计模式(5)共享模式/享元模式(Flyweight模式)
Java设计模式(6)桥模式(Bridge模式)
Java设计模式(7)装饰模式(Decorator模式)
Java设计模式(8)组合模式(Composite模式)
Java设计模式(9)适配器模式(Adapter模式)
Java设计模式(10)代理模式(Proxy模式)
Java设计模式(11)外观模式(Facade模式)
Java设计模式(12)迭代模式(Iterator模式)
Java设计模式(13)模板模式(Template模式)
Java设计模式(14)责任链模式(Chain of Responsibility模式)
Java设计模式(15)备忘录模式(Memento模式)
Java设计模式(16)中介模式(Mediator模式)
Java设计模式(17)解释器模式(Interpreter模式)
Java设计模式(18)策略模式(Strategy模式)
Java设计模式(19)状态模式(State模式)
Java设计模式(20)观察者模式(Observer模式)
Java设计模式(21)访问模式(Visitor者模式)
Java设计模式(22)命令模式(Command模式)
//bulider
// class Person{
/**/
public Person(20arg){
//参数太多,builder可以添加参数,避免不必要的参数
}
}
工厂模式的本质就是统一接口,比如有A、B、C三个类都继承于F,
然后有个工厂类D,那么A、B、C的创建就不是分别调用它们自己的创建方法,
而是D的同一个接口通过不同的参数来创建A、B、C,而D的这个返回值一般是F,
这样这个返回值的任何操作都是相应A、B、C里面的方法,既能够兼顾功能,
同时忽略了具体类型。
Timer内部是单线程,并不是并发运行的,一个任务抛出异常,全部任务也会停止
原型模式是一种创建型设计模式,它通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的.
原型模式多用于创建复杂的或者耗时的实例, 因为这种情况下,复制一个已经存在的实例可以使程序运行更高效,或者创建值相等,只是命名不一样的同类数据.
原型模式中的拷贝分为"浅拷贝"和"深拷贝":
浅拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象.
深拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制.
//序列化也可以实现deepCopy
public Object deepClone(){
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(this);
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
return oi.readObject();
} catch (IOException | ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
//abstractClass 抽象类可以把公有的行为和函数实现,,子类继承抽象类无需重复写代码,同时,新增加了一个接口,只要重新
//在抽象类那里写方法的实现就可以了,不需要在每个类里面写方法的实现,如果该类将来存在可以修改的空间,建议都增加一层抽象类实现
//example
Interface Bird{
void speak();
//new add//void fly();
}
class abstractBird implements Bird{
@Override
void speak(){
System.out.println("i am speaking");
}
//new add//
/@Override
void fly(){
System.out.println("i can fly now");
}**/
}
class BigBird extends Bird{
}
class SmallBird extends Bird{
}
//面向接口编程,而不是面向实现编程 // 不要在final类或者实现类里写不同方法的代码:::
/*Interface Fly{
void fly();
}
class FlyBySwings implements Fly{
void fly(){
/****/
/***/ 假如该鸟在不同时间段有不同的飞行行为,应该考虑用setFly,,set+行为特征/***/
}
}
class FlyByNothing implements Fly{
void fly(){
/****/
}
}
abstractClass ABird implements Bird{
Fly fly;
void setFlyBehaivor(Fly fly){
this.fly = fly;
// 行为的实现 fly = new FlyBySwings();或者fly = new FlyByNothing(); ???
}
}
https://www.zhihu.com/question/29444491 //*******???****//
////创业就是细分垄断 //book should read
redis // 类似mysql的内存数据库,读写很快
由于是各自独立的,所以要实现数据同步
//程序可以同时写redis和mysql,读redis
//用户名:lwb 密码:lwb
//项目管理
网友评论