精华内容
下载资源
问答
  • NULL 博文链接:https://pi88dian88.iteye.com/blog/1998800
  • 如题,最近用nginx搭建了一个静态资源服务器,对于同步或上传文件至静态资源服务器,大家有啥好点子不?
  • 进行多线程编程,同步控制是非常重要的,而同步控制就涉及到了锁。  对代码进行同步控制我们可以选择同步方法,也可以选择同步块,这两种方式各有优缺点,至于具体选择什么方式,就见仁见智了,同步块不仅可以更加...

    进行多线程编程,同步控制是非常重要的,而同步控制就涉及到了锁。

           对代码进行同步控制我们可以选择同步方法,也可以选择同步块,这两种方式各有优缺点,至于具体选择什么方式,就见仁见智了,同步块不仅可以更加精确的控制对象锁,也就是控制锁的作用域,何谓锁的作用域?锁的作用域就是从锁被获取到其被释放的时间。而且可以选择要获取哪个对象的对象锁。但是如果在使用同步块机制时,如果使用过多的锁也会容易引起死锁问题,同时获取和释放所也有代价,而同步方法,它们所拥有的锁就是该方法所属的类的对象锁,换句话说,也就是this对象,而且锁的作用域也是整个方法,这可能导致其锁的作用域可能太大,也有可能引起死锁,同时因为可能包含了不需要进行同步的代码块在内,也会降低程序的运行效率。而不管是同步方法还是同步块,我们都不应该在他们的代码块内包含无限循环,如果代码内部要是有了无限循环,那么这个同步方法或者同步块在获取锁以后因为代码会一直不停的循环着运行下去,也就没有机会释放它所获取的锁,而其它等待这把锁的线程就永远无法获取这把锁,这就造成了一种死锁现象。

       详细解说一下同步方法的锁,同步方法分为静态同步方法与非静态同步方法。

           所有的非静态同步方法用的都是同一把锁——实例对象本身,也就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已获取锁的非静态同步方法释放锁就可以获取他们自己的锁。

            而所有的静态同步方法用的也是同一把锁——类对象本身,这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同步方法之间,只要它们同一个类的实例对象!

        而对于同步块,由于其锁是可以选择的,所以只有使用同一把锁的同步块之间才有着竞态条件,这就得具体情况具体分析了,但这里有个需要注意的地方,同步块的锁是可以选择的,但是不是可以任意选择的!!!!这里必须要注意一个物理对象和一个引用对象的实例变量之间的区别!使用一个引用对象的实例变量作为锁并不是一个好的选择,因为同步块在执行过程中可能会改变它的值,其中就包括将其设置为null,而对一个null对象加锁会产生异常,并且对不同的对象加锁也违背了同步的初衷!这看起来是很清楚的,但是一个经常发生的错误就是选用了错误的锁对象,因此必须注意:同步是基于实际对象而不是对象引用的!多个变量可以引用同一个对象,变量也可以改变其值从而指向其他的对象,因此,当选择一个对象锁时,我们要根据实际对象而不是其引用来考虑!作为一个原则,不要选择一个可能会在锁的作用域中改变值的实例变量作为锁对象!!!!

     

    Java线程:线程的同步与锁

     

     
     
     
    一、同步问题提出
     
    线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏。
    例如:两个线程ThreadA、ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据。
     
    public  class Foo {       private  int x = 100;       public  int getX() {           return x;      }       public  int fix( int y) {         x = x - y;           return x;      }  }
     
    public  class MyRunnable  implements Runnable {       private Foo foo =  new Foo();      public  static  void main(String[] args) {          MyRunnable r =  new MyRunnable();          Thread ta =  new Thread(r,  "Thread-A");          Thread tb =  new Thread(r,  "Thread-B");          ta.start();          tb.start();     }       public  void run() {           for ( int i = 0; i < 3; i++) {               this.fix(30);               try {                 Thread.sleep(1);              }  catch (InterruptedException e) {                  e.printStackTrace();             }              System.out.println(Thread.currentThread().getName() +  ": 当前foo对象的x值=" + foo.getX());          }      }       public  int fix( int y) {           return foo.fix(y);      }  }
     
    运行结果:
    Thread-A : 当前foo对象的x值= 40  Thread-B : 当前foo对象的x值= 40  Thread-B : 当前foo对象的x值= -20 Thread-A : 当前foo对象的x值= -50  Thread-A : 当前foo对象的x值= -80  Thread-B : 当前foo对象的x值= -80 Process finished with exit code 0
     
              从结果发现,这样的输出值明显是不合理的。原因是两个线程不加控制的访问Foo对象并修改其数据所致。
     
            如果要保持结果的合理性,只需要达到一个目的,就是将对Foo的访问加以限制,每次只能有一个线程在访问。这样就能保证Foo对象中数据的合理性了。
     
    在具体的Java代码中需要完成一下两个操作:
    把竞争访问的资源类Foo变量x标识为private;
    同步哪些修改变量的代码,使用synchronized关键字同步方法或代码。
     
    二、同步和锁定
     
    1、锁的原理
     
    Java中每个对象都有一个内置锁
     
              当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this实例)有关的锁。获得一个对象的锁也称为获取锁、锁定对象、在对象上锁定或在对象上同步。
     
    当程序运行到synchronized同步方法或代码块时才该对象锁才起作用。
     
                 一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放。
     
    释放锁是指持锁线程退出了synchronized同步方法或代码块。
     
    关于锁和同步,有一下几个要点:
    1)、 只能同步方法,而不能同步变量和类;
    2 )、每个对象只有一个锁;当提到同步时,应该清楚在什么上同步?也就是说,在哪个对象上同步?
    3)、 不必同步类中所有的方法,类可以同时拥有同步和非同步方法。
    4) 、如果两个线程要执行一个类中的synchronized方法,并且两个线程使用相同的实例来调用方法,那么一次只能有一个线程能够执行方法,另一个需要等待,直到锁被释放。也就是说:如果一个线程在对象上获得一个锁,就没有任何其他线程可以进入(该对象的)类中的任何一个同步方法
    5)、 如果线程拥有同步和非同步方法,则非同步方法可以被多个线程自由访问而不受锁的限制。

    6)、线程睡眠时,它所持的任何锁都不会释放。

    7 )、线程可以获得多个重进入(synchronized )锁。比如,在一个对象的同步方法里面调用另外一个对象的同步方法,则获取了两个对象的同步锁。

     

    8)、同步损害并发性,应该尽可能缩小同步范围。同步不但可以同步整个方法,还可以同步方法中一部分代码块。
    9 )、在使用同步代码块时候,应该指定在哪个对象上同步,也就是说要获取哪个对象的锁。例如:
        public int fix(int y) {         synchronized (this) {             x = x - y;         }         return x;     }
     
    当然,同步方法也可以改写为非同步方法,但功能完全一样的,例如:
        public synchronized int getX() {         return x++;     }
        public int getX() {         synchronized (this) {             return x;         }     }
    效果是完全一样的。
     
    三、静态方法同步
     
    要同步静态方法,需要一个用于整个类对象的锁,这个对象是就是这个类(XXX.class)。
    例如:
    public static synchronized int setName(String name){
          Xxx.name = name;
    }
    等价于 public static int setName(String name){       synchronized(Xxx.class){             Xxx.name = name;       } }
     
    四、如果线程不能不能获得锁会怎么样
     
           如果线程试图进入同步方法,而其锁已经被占用,则线程在该对象上被阻塞。实质上,线程进入该对象的的一种池中,必须在哪里等待,直到其锁被释放,该线程再次变为可运行或运行为止。
     
    当考虑阻塞时,一定要注意哪个对象正被用于锁定:
    1、调用同一个对象中非静态同步方法的线程将彼此阻塞。如果是不同对象,则每个线程有自己的对象的锁,线程间彼此互不干预。
     
    2、调用同一个类中的静态同步方法的线程将彼此阻塞,它们都是锁定在相同的Class对象上。
     
    3 、静态同步方法和非静态同步方法将永远不会彼此阻塞,因为静态方法锁定在Class对象上,非静态方法锁定在该类的对象上。
     
    4、对于同步代码块,要看清楚什么对象已经用于锁定(synchronized后面括号的内容)。在同一个对象上进行同步的线程将彼此阻塞,在不同对象上锁定的线程将永远不会彼此阻塞。
     
    五、何时需要同步
     
          在多个线程同时访问互斥(可交换)数据时,应该同步以保护数据,确保两个线程不会同时修改更改它。
     
    对于非静态字段中可更改的数据,通常使用非静态方法访问。
    对于静态字段中可更改的数据,通常使用静态方法访问
     
    如果需要在非静态方法中使用静态字段,或者在静态字段中调用非静态方法,问题将变得非常复杂。已经超出SJCP考试范围了。
     
    六、线程安全类
     
          当一个类已经很好的同步以保护它的数据时,这个类就称为“线程安全的”。
     即使是线程安全类,也应该特别小心,因为操作的线程是间仍然不一定安全。
     
    举个形象的例子,比如一个集合是线程安全的,有两个线程在操作同一个集合对象,当第一个线程查询集合非空后,删除集合中所有元素的时候。第二个线程也来执行与第一个线程相同的操作,也许在第一个线程查询后,第二个线程也查询出集合非空,但是当第一个执行清除后,第二个再执行删除显然是不对的,因为此时集合已经为空了。
    看个代码:
     
    public  class NameList {       private List nameList = Collections.synchronizedList( new LinkedList());      public  void add(String name) {          nameList.add(name);      }       public String removeFirst() {          if (nameList.size() > 0) {               return (String) nameList.remove(0);          }  else {               return  null;         }      }  }
     
    public  class Test {       public  static  void main(String[] args) {           final NameList nl =  new NameList();         nl.add( "aaa");           class NameDropper  extends Thread{               public  void run(){                  String name = nl.removeFirst();                  System.out.println(name);              }          }          Thread t1 =  new NameDropper();          Thread t2 =  new NameDropper();          t1.start();          t2.start();      }  }
     
    虽然集合对象
        private List nameList = Collections.synchronizedList(new LinkedList());是同步的,但是程序还不是线程安全的。出现这种事件的原因是,上例中一个线程操作列表过程中无法阻止另外一个线程对列表的其他操作。
     
    解决上面问题的办法是,在操作集合对象的NameList上面做一个同步。改写后的代码如下:
    public  class NameList {       private List nameList = Collections.synchronizedList( new LinkedList());      public  synchronized  void add(String name) {          nameList.add(name);      }      public  synchronized String removeFirst() {           if (nameList.size() > 0) {               return (String) nameList.remove(0);          }  else {               return  null;          }      }  }
     
    这样,当一个线程访问其中一个同步方法时,其他线程只有等待。
     
    七、线程死锁
     
           死锁对Java程序来说,是很复杂的,也很难发现问题。当两个线程被阻塞,每个线程在等待另一个线程时就发生死锁。
     
    还是看一个比较直观的死锁例子:
     
    public  class DeadlockRisk {       private  static  class Resource {           public  int value;      }       private Resource resourceA =  new Resource();       private Resource resourceB =  new Resource();       public  int read() {          synchronized (resourceA) {               synchronized (resourceB) {                   return resourceB.value + resourceA.value;              }          }      }       public  void write( int a,  int b) {           synchronized (resourceB) {              synchronized (resourceA) {                  resourceA.value = a;                  resourceB.value = b;              }         }      }  }
     
            假设read()方法由一个线程启动,write()方法由另外一个线程启动。读线程将拥有resourceA锁,写线程将拥有resourceB锁,两者都坚持等待的话就出现死锁。
     
            实际上,上面这个例子发生死锁的概率很小。因为在代码内的某个点,CPU必须从读线程切换到写线程,所以,死锁基本上不能发生。
     
             但是,无论代码中发生死锁的概率有多小,一旦发生死锁,程序就死掉。有一些设计方法能帮助避免死锁,包括始终按照预定义的顺序获取锁这一策略。已经超出SCJP的考试范围。
     
    八、线程同步小结
     
    1、线程同步的目的是为了保护多个线程反问一个资源时对资源的破坏。
    2、 线程同步方法是通过锁来实现,每个对象都有切仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其他访问该对象的线程就无法再访问该对象的其他同步方法。
    3、对于静态同步方法,锁是针对这个类的,锁对象是该类的Class对象。静态和非静态方法的锁互不干预。一个线程获得锁,当在一个同步方法中访问另外对象上的同步方法时,会获取这两个对象锁。
    4、对于同步,要时刻清醒在哪个对象上同步,这是关键。
    5、 编写线程安全的类,需要时刻注意对多个线程竞争访问资源的逻辑和安全做出正确的判断,对“原子”操作做出分析,并保证原子操作期间别的线程无法访问竞争资源。
    6、当多个线程等待一个对象锁时,没有获取到锁的线程将发生阻塞。
    7、死锁是线程间相互等待锁锁造成的,在实际中发生的概率非常的小。真让你写个死锁程序,不一定好使,呵呵。但是,一旦程序发生死锁,程序将死掉。

     

     

     

     

     

    Java代码   收藏代码
    1. package com.etrip.concurrent.executor;  
    2.   
    3. import java.util.Collections;  
    4. import java.util.HashMap;  
    5. import java.util.Iterator;  
    6. import java.util.Map;  
    7. import java.util.Map.Entry;  
    8. import java.util.Set;  
    9. /** 
    10.  * 非静态同步方法,静态同步方法,同步语句块的使用 
    11.  *  
    12.  *  
    13.  * 进行多线程编程,同步控制是非常重要的,而同步控制就涉及到了锁。  
    14.  
    15.        对代码进行同步控制我们可以选择同步方法,也可以选择同步块,这两种方式各有优缺点,至于具体选择什么方式,就见仁见智了,同步块不仅可以更加精确的控制对象锁,也就是控制锁的作用域,何谓锁的作用域?锁的作用域就是从锁被获取到其被释放的时间。而且可以选择要获取哪个对象的对象锁。但是如果在使用同步块机制时,如果使用过多的锁也会容易引起死锁问题,同时获取和释放所也有代价,而同步方法,它们所拥有的锁就是该方法所属的类的对象锁,换句话说,也就是this对象,而且锁的作用域也是整个方法,这可能导致其锁的作用域可能太大,也有可能引起死锁,同时因为可能包含了不需要进行同步的代码块在内,也会降低程序的运行效率。而不管是同步方法还是同步块,我们都不应该在他们的代码块内包含无限循环,如果代码内部要是有了无限循环,那么这个同步方法或者同步块在获取锁以后因为代码会一直不停的循环着运行下去,也就没有机会释放它所获取的锁,而其它等待这把锁的线程就永远无法获取这把锁,这就造成了一种死锁现象。  
    16.  *  
    17.  * @author longgangbai 
    18.  */  
    19. public class StaticInstanceLock {  
    20.       
    21.       
    22.     private   int count;  
    23.     private  static  StaticInstanceLock  instance=null;  
    24.     private StaticInstanceLock(){  
    25.     }  
    26.     /** 
    27.      * 静态方法的锁 
    28.      *  
    29.      * @return 
    30.      */  
    31.     public static synchronized StaticInstanceLock getInstance(){  
    32.         if(instance==null){  
    33.             instance=new  StaticInstanceLock();  
    34.         }  
    35.         return instance;  
    36.     }  
    37.   
    38.  本文转载自http://www.thinksaas.cn/group/topic/96902/ (感谢作者的辛勤总结。。。)
    展开全文
  • java synchronized静态同步方法与非静态同步方法,同步语句块 并发编程线程同步静态方法锁非静态方法锁同步块   进行多线程编程,同步控制是非常重要的,而同步控制就涉及到了锁。  对代码进行同步...
     
    

            进行多线程编程,同步控制是非常重要的,而同步控制就涉及到了锁。

           对代码进行同步控制我们可以选择同步方法,也可以选择同步块,这两种方式各有优缺点,至于具体选择什么方式,就见仁见智了,同步块不仅可以更加精确的控制对象锁,也就是控制锁的作用域,何谓锁的作用域?锁的作用域就是从锁被获取到其被释放的时间。而且可以选择要获取哪个对象的对象锁。但是如果在使用同步块机制时,如果使用过多的锁也会容易引起死锁问题,同时获取和释放所也有代价,而同步方法,它们所拥有的锁就是该方法所属的类的对象锁,换句话说,也就是this对象,而且锁的作用域也是整个方法,这可能导致其锁的作用域可能太大,也有可能引起死锁,同时因为可能包含了不需要进行同步的代码块在内,也会降低程序的运行效率。而不管是同步方法还是同步块,我们都不应该在他们的代码块内包含无限循环,如果代码内部要是有了无限循环,那么这个同步方法或者同步块在获取锁以后因为代码会一直不停的循环着运行下去,也就没有机会释放它所获取的锁,而其它等待这把锁的线程就永远无法获取这把锁,这就造成了一种死锁现象。


     
     详细解说一下同步方法的锁,同步方法分为静态同步方法与非静态同步方法。

           所有的非静态同步方法用的都是同一把锁——实例对象本身,也就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已获取锁的非静态同步方法释放锁就可以获取他们自己的锁。

            而所有的静态同步方法用的也是同一把锁——类对象本身,这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同步方法之间,只要它们同一个类的实例对象!

        而对于同步块,由于其锁是可以选择的,所以只有使用同一把锁的同步块之间才有着竞态条件,这就得具体情况具体分析了,但这里有个需要注意的地方,同步块的锁是可以选择的,但是不是可以任意选择的!!!!这里必须要注意一个物理对象和一个引用对象的实例变量之间的区别!使用一个引用对象的实例变量作为锁并不是一个好的选择,因为同步块在执行过程中可能会改变它的值,其中就包括将其设置为null,而对一个null对象加锁会产生异常,并且对不同的对象加锁也违背了同步的初衷!这看起来是很清楚的,但是一个经常发生的错误就是选用了错误的锁对象,因此必须注意:同步是基于实际对象而不是对象引用的!多个变量可以引用同一个对象,变量也可以改变其值从而指向其他的对象,因此,当选择一个对象锁时,我们要根据实际对象而不是其引用来考虑!作为一个原则,不要选择一个可能会在锁的作用域中改变值的实例变量作为锁对象!!!!

     

    Java线程:线程的同步与锁

     
     
     
    一、同步问题提出
     
    线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏。
    例如:两个线程ThreadA、ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据。
     
    public  class Foo { 
         private  int x = 100; 

         public  int getX() { 
             return x; 
        } 

         public  int fix( int y) { 
            x = x - y; 
             return x; 
        } 
    }
     
    public  class MyRunnable  implements Runnable { 
         private Foo foo =  new Foo(); 

         public  static  void main(String[] args) { 
            MyRunnable r =  new MyRunnable(); 
            Thread ta =  new Thread(r,  "Thread-A"); 
            Thread tb =  new Thread(r,  "Thread-B"); 
            ta.start(); 
            tb.start(); 
        } 

         public  void run() { 
             for ( int i = 0; i < 3; i++) { 
                 this.fix(30); 
                 try { 
                    Thread.sleep(1); 
                }  catch (InterruptedException e) { 
                    e.printStackTrace(); 
                } 
                System.out.println(Thread.currentThread().getName() +  " : 当前foo对象的x值= " + foo.getX()); 
            } 
        } 

         public  int fix( int y) { 
             return foo.fix(y); 
        } 
    }
     
    运行结果:
    Thread-A : 当前foo对象的x值= 40 
    Thread-B : 当前foo对象的x值= 40 
    Thread-B : 当前foo对象的x值= -20 
    Thread-A : 当前foo对象的x值= -50 
    Thread-A : 当前foo对象的x值= -80 
    Thread-B : 当前foo对象的x值= -80 

    Process finished with exit code 0
     
              从结果发现,这样的输出值明显是不合理的。原因是两个线程不加控制的访问Foo对象并修改其数据所致。
     
            如果要保持结果的合理性,只需要达到一个目的,就是将对Foo的访问加以限制,每次只能有一个线程在访问。这样就能保证Foo对象中数据的合理性了。
     
    在具体的Java代码中需要完成一下两个操作:
    把竞争访问的资源类Foo变量x标识为private;
    同步哪些修改变量的代码,使用synchronized关键字同步方法或代码。
     
    二、同步和锁定
     
    1、锁的原理
     
    Java中每个对象都有一个内置锁
     
              当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this实例)有关的锁。获得一个对象的锁也称为获取锁、锁定对象、在对象上锁定或在对象上同步。
     
    当程序运行到synchronized同步方法或代码块时才该对象锁才起作用。
     
                 一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放。
     
    释放锁是指持锁线程退出了synchronized同步方法或代码块。
     
    关于锁和同步,有一下几个要点:
    1)、 只能同步方法,而不能同步变量和类;
    2 )、每个对象只有一个锁;当提到同步时,应该清楚在什么上同步?也就是说,在哪个对象上同步?
    3)、 不必同步类中所有的方法,类可以同时拥有同步和非同步方法。
    4) 、如果两个线程要执行一个类中的synchronized方法,并且两个线程使用相同的实例来调用方法,那么一次只能有一个线程能够执行方法,另一个需要等待,直到锁被释放。也就是说:如果一个线程在对象上获得一个锁,就没有任何其他线程可以进入(该对象的)类中的任何一个同步方法
    5)、 如果线程拥有同步和非同步方法,则非同步方法可以被多个线程自由访问而不受锁的限制。

    6)、线程睡眠时,它所持的任何锁都不会释放。

    7 )、线程可以获得多个重进入(synchronized )锁。比如,在一个对象的同步方法里面调用另外一个对象的同步方法,则获取了两个对象的同步锁。

    8)、同步损害并发性,应该尽可能缩小同步范围。同步不但可以同步整个方法,还可以同步方法中一部分代码块。
    9 )、在使用同步代码块时候,应该指定在哪个对象上同步,也就是说要获取哪个对象的锁。例如:
        public int fix(int y) {
            synchronized (this) {
                x = x - y;
            }
            return x;
        }
     
    当然,同步方法也可以改写为非同步方法,但功能完全一样的,例如:
        public synchronized int getX() {
            return x++;
        }
        public int getX() {
            synchronized (this) {
                return x;
            }
        }
    效果是完全一样的。
     
    三、静态方法同步
     
    要同步静态方法,需要一个用于整个类对象的锁,这个对象是就是这个类(XXX.class)。
    例如:
    public static synchronized int setName(String name){
          Xxx.name = name;
    }
    等价于
    public static int setName(String name){
          synchronized(Xxx.class){
                Xxx.name = name;
          }
    }

     
    四、如果线程不能不能获得锁会怎么样
     
           如果线程试图进入同步方法,而其锁已经被占用,则线程在该对象上被阻塞。实质上,线程进入该对象的的一种池中,必须在哪里等待,直到其锁被释放,该线程再次变为可运行或运行为止。
     
    当考虑阻塞时,一定要注意哪个对象正被用于锁定:
    1、调用同一个对象中非静态同步方法的线程将彼此阻塞。如果是不同对象,则每个线程有自己的对象的锁,线程间彼此互不干预。
     
    2、调用同一个类中的静态同步方法的线程将彼此阻塞,它们都是锁定在相同的Class对象上。
     
    3 、静态同步方法和非静态同步方法将永远不会彼此阻塞,因为静态方法锁定在Class对象上,非静态方法锁定在该类的对象上。
     
    4、对于同步代码块,要看清楚什么对象已经用于锁定(synchronized后面括号的内容)。在同一个对象上进行同步的线程将彼此阻塞,在不同对象上锁定的线程将永远不会彼此阻塞。
     
    五、何时需要同步
     
          在多个线程同时访问互斥(可交换)数据时,应该同步以保护数据,确保两个线程不会同时修改更改它。
     
    对于非静态字段中可更改的数据,通常使用非静态方法访问。
    对于静态字段中可更改的数据,通常使用静态方法访问
     
    如果需要在非静态方法中使用静态字段,或者在静态字段中调用非静态方法,问题将变得非常复杂。已经超出SJCP考试范围了。
     
    六、线程安全类
     
          当一个类已经很好的同步以保护它的数据时,这个类就称为“线程安全的”。
     即使是线程安全类,也应该特别小心,因为操作的线程是间仍然不一定安全。
     
    举个形象的例子,比如一个集合是线程安全的,有两个线程在操作同一个集合对象,当第一个线程查询集合非空后,删除集合中所有元素的时候。第二个线程也来执行与第一个线程相同的操作,也许在第一个线程查询后,第二个线程也查询出集合非空,但是当第一个执行清除后,第二个再执行删除显然是不对的,因为此时集合已经为空了。
    看个代码:
     
    public  class NameList { 
         private List nameList = Collections.synchronizedList( new LinkedList()); 

         public  void add(String name) { 
            nameList.add(name); 
        } 

         public String removeFirst() { 
             if (nameList.size() > 0) { 
                 return (String) nameList.remove(0); 
            }  else { 
                 return  null
            } 
        } 
    }
     
    public  class Test { 
         public  static  void main(String[] args) { 
             final NameList nl =  new NameList(); 
            nl.add( "aaa"); 
             class NameDropper  extends Thread{ 
                 public  void run(){ 
                    String name = nl.removeFirst(); 
                    System.out.println(name); 
                } 
            } 

            Thread t1 =  new NameDropper(); 
            Thread t2 =  new NameDropper(); 
            t1.start(); 
            t2.start(); 
        } 
    }
     
    虽然集合对象
        private List nameList = Collections.synchronizedList(new LinkedList());是同步的,但是程序还不是线程安全的。出现这种事件的原因是,上例中一个线程操作列表过程中无法阻止另外一个线程对列表的其他操作。
     
    解决上面问题的办法是,在操作集合对象的NameList上面做一个同步。改写后的代码如下:
    public  class NameList { 
         private List nameList = Collections.synchronizedList( new LinkedList()); 

         public  synchronized  void add(String name) { 
            nameList.add(name); 
        } 

         public  synchronized String removeFirst() { 
             if (nameList.size() > 0) { 
                 return (String) nameList.remove(0); 
            }  else { 
                 return  null
            } 
        } 
    }
     
    这样,当一个线程访问其中一个同步方法时,其他线程只有等待。
     
    七、线程死锁
     
           死锁对Java程序来说,是很复杂的,也很难发现问题。当两个线程被阻塞,每个线程在等待另一个线程时就发生死锁。
     
    还是看一个比较直观的死锁例子:
     
    public  class DeadlockRisk { 
         private  static  class Resource { 
             public  int value; 
        } 

         private Resource resourceA =  new Resource(); 
         private Resource resourceB =  new Resource(); 

         public  int read() { 
             synchronized (resourceA) { 
                 synchronized (resourceB) { 
                     return resourceB.value + resourceA.value; 
                } 
            } 
        } 

         public  void write( int a,  int b) { 
             synchronized (resourceB) { 
                 synchronized (resourceA) { 
                    resourceA.value = a; 
                    resourceB.value = b; 
                } 
            } 
        } 
    }
     
            假设read()方法由一个线程启动,write()方法由另外一个线程启动。读线程将拥有resourceA锁,写线程将拥有resourceB锁,两者都坚持等待的话就出现死锁。
     
            实际上,上面这个例子发生死锁的概率很小。因为在代码内的某个点,CPU必须从读线程切换到写线程,所以,死锁基本上不能发生。
     
             但是,无论代码中发生死锁的概率有多小,一旦发生死锁,程序就死掉。有一些设计方法能帮助避免死锁,包括始终按照预定义的顺序获取锁这一策略。已经超出SCJP的考试范围。
     
    八、线程同步小结
     
    1、线程同步的目的是为了保护多个线程反问一个资源时对资源的破坏。
    2、 线程同步方法是通过锁来实现,每个对象都有切仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其他访问该对象的线程就无法再访问该对象的其他同步方法。
    3、对于静态同步方法,锁是针对这个类的,锁对象是该类的Class对象。静态和非静态方法的锁互不干预。一个线程获得锁,当在一个同步方法中访问另外对象上的同步方法时,会获取这两个对象锁。
    4、对于同步,要时刻清醒在哪个对象上同步,这是关键。
    5、 编写线程安全的类,需要时刻注意对多个线程竞争访问资源的逻辑和安全做出正确的判断,对“原子”操作做出分析,并保证原子操作期间别的线程无法访问竞争资源。
    6、当多个线程等待一个对象锁时,没有获取到锁的线程将发生阻塞。
    7、死锁是线程间相互等待锁锁造成的,在实际中发生的概率非常的小。真让你写个死锁程序,不一定好使,呵呵。但是,一旦程序发生死锁,程序将死掉。

     

     

     

     

    Java代码   收藏代码
    1. package com.etrip.concurrent.executor;  
    2.   
    3. import java.util.Collections;  
    4. import java.util.HashMap;  
    5. import java.util.Iterator;  
    6. import java.util.Map;  
    7. import java.util.Map.Entry;  
    8. import java.util.Set;  
    9. /** 
    10.  * 非静态同步方法,静态同步方法,同步语句块的使用 
    11.  *  
    12.  *  
    13.  * 进行多线程编程,同步控制是非常重要的,而同步控制就涉及到了锁。  
    14.  
    15.        对代码进行同步控制我们可以选择同步方法,也可以选择同步块,这两种方式各有优缺点,至于具体选择什么方式,就见仁见智了,同步块不仅可以更加精确的控制对象锁,也就是控制锁的作用域,何谓锁的作用域?锁的作用域就是从锁被获取到其被释放的时间。而且可以选择要获取哪个对象的对象锁。但是如果在使用同步块机制时,如果使用过多的锁也会容易引起死锁问题,同时获取和释放所也有代价,而同步方法,它们所拥有的锁就是该方法所属的类的对象锁,换句话说,也就是this对象,而且锁的作用域也是整个方法,这可能导致其锁的作用域可能太大,也有可能引起死锁,同时因为可能包含了不需要进行同步的代码块在内,也会降低程序的运行效率。而不管是同步方法还是同步块,我们都不应该在他们的代码块内包含无限循环,如果代码内部要是有了无限循环,那么这个同步方法或者同步块在获取锁以后因为代码会一直不停的循环着运行下去,也就没有机会释放它所获取的锁,而其它等待这把锁的线程就永远无法获取这把锁,这就造成了一种死锁现象。  
    16.  *  
    17.  * @author longgangbai 
    18.  */  
    19. public class StaticInstanceLock {  
    20.       
    21.       
    22.     private   int count;  
    23.     private  static  StaticInstanceLock  instance=null;  
    24.     private StaticInstanceLock(){  
    25.     }  
    26.     /** 
    27.      * 静态方法的锁 
    28.      *  
    29.      * @return 
    30.      */  
    31.     public static synchronized StaticInstanceLock getInstance(){  
    32.         if(instance==null){  
    33.             instance=new  StaticInstanceLock();  
    34.         }  
    35.         return instance;  
    36.     }  
    37.   
    38.     /** 
    39.      * 非静态方法的锁 
    40.      * @return 
    41.      */  
    42.     public synchronized int getCount(){  
    43.         return count;  
    44.     }  
    45.       
    46.     public synchronized  void setCount(int count){  
    47.         this.count=count;  
    48.     }  
    49.     /** 
    50.      * 同步语句块的使用 
    51.      *  
    52.      */  
    53.     public void synmethod(){  
    54.               //HashMap为非安全性Map  
    55.               HashMap<String,String> hashmap = new HashMap<String,String>();  
    56.               hashmap.put("ZH","中国");  
    57.               hashmap.put("EN","英国");  
    58.               hashmap.put("AM","美国");  
    59.               hashmap.put("FR","法国");  
    60.                 
    61.               //创建一个同步的对象Map  
    62.               Map<String,String> m = Collections.synchronizedMap(hashmap);  
    63.               Set<String> s = m.keySet();  // Needn't be in synchronized block  
    64.               //这里同步的对象均为需要使用同步的对象如Map而非Set  
    65.               synchronized(m) {  // Synchronizing on m, not s!  
    66.                   Iterator<String> i = s.iterator(); // Must be in synchronized block  
    67.                   while (i.hasNext()){  
    68.                       foo(i.next());  
    69.                   }  
    70.               }  
    71.     }  
    72.       
    73.     public void foo(String entry){  
    74.         System.out.println("StaticInstanceLock ="+entry);  
    75.     }  
    76.       
    77.     public static void main(String[] args) {  
    78.       
    79.         StaticInstanceLock instance=StaticInstanceLock.getInstance();  
    80.         instance.setCount(7);  
    81.         int count = instance.getCount();  
    82.         instance.synmethod();  
    83.     }  
    84.       
    85. }
    展开全文
  • 静态资源CDN

    千次阅读 2017-07-28 09:03:17
    静态资源(static resources) : js , css , img 等非服务器动态运行生成的文件 在一般的网站中,静态资源使用频率高,流量占用大。对于有追求(访问量稍大)的网站,都会把静态资源放置到CDN服务器,不占用业务...

    静态资源CDN

    参考地址: http://blog.csdn.net/u013063153/article/details/52806155

    静态资源(static resources) : js , css , img 等非服务器动态运行生成的文件

    在一般的网站中,静态资源使用频率高,流量占用大。对于有追求(访问量稍大)的网站,都会把静态资源放置到CDN服务器,不占用业务服务器的网络带宽,从而达到更好的用户体验。那大公司的静态资源怎么发布呢?

    发布要求

    1. 静态资源必须走CDN

    2. 平滑升级–非覆盖式发布

    在不修改线上静态资源的情况下,发布新的静态资源。即CDN上的静态资源必须共存多个静态版本

    • 先部署页面,再部署资源。 结果:新的页面访问了一个旧的资源,除非手动刷新,否则在资源缓存过期之前,页面会一直执行错误。
    • 先部署资源,再部署页面。 结果:有本地缓存的正常;没有本地缓存的,旧的页面加载新的资源,导致页面执行错误,当页面部署完成,访问才恢复正常。

      1. 精确的版本控制–文件版本号

    更新静态资源,只更改修改的部分。不能修改未更新的资源的引用。

    全量的更新静态资源对于用户和服务器的提供者来说是非常不友好的,极度浪费CDN资源和用户流量。在CDN的配置中,会把缓存时间设置很长。

    解决方案:根据文件的内容算出一个值,如果文件内容不改变,那么这个值就不会改变。

    发布和问题

    发布流程

    如果我们把静态资源的实际访问域名设置为 res.company.com。

    1. 功能开发结束后,开发人员把静态资源提交到测试环境 Git 仓库。

    2. 测试人员在测试环境通过绑定 host 的方式测试,测试通过后,进入发布阶段,需要静态资源

    代码提交到产品环境 git 仓库。(使用测试和产品两个仓库,是为了测试和产品环境完全隔离)

    1. 源站(origin.res.company.com)从产品环境 Git 拉取静态资源的代码,并且为静态资源

    提供访问服务(nginx 等),该域名不提供文件缓存服务,仅仅作为 CDN 的回源地址。所以代码

    中一定不要写源站的信息。
    4. 在 CDN 服务商提供的空间中,将回源地址配置为源站(origin.res.company.com)。

    1. CDN 服务器会提供一个默认的访问域名,比如 cdn-1.res.cdn_company.com, 然后把实际需求访问的静态资源域名res.company.com CNAME 到 cdn-1.res.cdn_company.com。

    2. 代码发布完毕。用户访问的时候,会访问到最近的 CDN 阶段。CDN 结点去文件中心取文件,

    如果不存在文件则回源到源站,获取文件。(有些 CDN 产品提供文件存储功能,异地备份)

    1. 通过这样的流程,就能让用户访通过 CDN 访问到我们的实际资源。

    怎么做到多个项目共存

    结论:我们会按照目录来划分业务的静态资源。

    res.company.com域名下面会共存多个业务。A业务,B业务都是使用同样的发布方案。

    比如:某静态资源的访问路径为: http://res.company.com/:业务名/js/xxx.xxx.js

    多个团队可以使用同一个静态资源仓库,res.git,然后按照目录来区分业务。web 服务器直接指

    向到 res/即可。静态资源更新只需要 pull 代码即可,而不需求做其他改动。

    是否同源站文件到CDN

    同步源文件到CDN能确保实现非覆盖式发布。

    最后

    1. 终端用户就近访问 CDN 加速节点上的资源
    2. 若 CDN 加速节点上不存在资源,则回源获取资源
    3. 回源获取的资源持久化存储到 CDN
    4. 返回资源内容给终端用户
    5. 当终端用户再次访问相同的资源时,CDN 的加速节点将直接返回资源内容,不需要重新回源获取

    大公司开发部署前端代码

    观赏网址: https://www.zhihu.com/question/20790576

    负载均衡

    观赏网址: http://blog.csdn.net/wireless_com/article/details/52761138

    展开全文
  • Java中的同步块用synchronized标记。同步块在Java中是同步在某个对象上。所有同步在一个对象上的同步块在同时只能被一个线程进入并执行...4.静态方法中的同步块 在分别讲这4个同步块的区别前需要首先了解下Java中s...

    Java中的同步块用synchronized标记。同步块在Java中是同步在某个对象上。所有同步在一个对象上的同步块在同时只能被一个线程进入并执行操作。所有其他等待进入该同步块的线程将被阻塞,直到执行该同步块中的线程退出。

    并且存在4中不同的同步块
    1.实例方法
    2.静态方法
    3.实例方法中的同步块
    4.静态方法中的同步块

    在分别讲这4个同步块的区别前需要首先了解下Java中synchronized的原理。
    Java的同步机制是通过对对象(资源)加锁实现的,举个栗子:
    现在有一个对象A,线程T1和T2都会修改对象A的值。
    首先假设线程T1比线程T2更早运行到修改对象A的代码。
    此时线程T1修改对象A的流程应该是这样的:线程T1从主存中获取对象A,并在自己缓存中存下对象A的副本,然后修改自己缓存中的对象A的副本。修改完毕后将自己缓存中的对象A的副本赋值给主存中的对象A,实现对象A的修改。
    但是在线程T1执行修改对象A时,线程T2可能也跑到了修改对象A值的代码,而此时线程T1还在修改自己缓存中的对象A的副本,还没有将副本更新到主存中的对象A,但是线程T2又不知道,所以直接就从主存去取对象A了,这样就出现了竞态条件
    直观点,如果A=1,T1&T2都是将A+1,那么我们期望执行完T1&T2后A=3,但是上面栗子中最后A=2,因此我们为了防止这种竞态条件的出现,就需要给对象A加锁。
    在上面的例子中当线程T1从主存获取对象A时,对象A就会加锁,这时如果线程T2要从主存中取对象A时就会被阻塞,直到线程T1完成对主存中对象A的修改,这时锁会被打开,线程T2才可以调用对象A。

    实例方法

    实例方法(类的非静态方法)同步是同步在拥有该方法的对象上的,即加锁会加在对象上。
    比如:有多个线程调用一个对象的多个函数(限定下,只有同步函数会被多个线程重复调用)时。任何一个线程在调用函数时将会判断这个函数是否是同步函数(即加了synchronized关键字),如果是,则会去检查该方法的对象(拥有者)是否已经加锁,如果加锁了,该线程就会阻塞,等待该对象解锁;如果是同步函数且对象没有加锁,则会继续运行,并给对象加锁;如果不是同步函数的话,就不需要去检查对象是否加锁,直接可以继续运行。

    可以看下示例:
    现在有sTest 类,包含2个(add,add2)同步实例(非静态)方法,一个(addX1)实例(非静态)方法。

    public class sTest {
        public synchronized void add(){
            for(int i=0 ;i<100;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
        public synchronized void add2(){
            for(int i=100 ;i<200;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
        public void addX1(){
            for(int i=200 ;i<300;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }

    现在新建4个线程,并分别命名为thread1-4,所有线程全都只执行sTest 的实例对象Test的一个方法。其中1运行add,2运行add2,3运行add,4运行addX1。

    public class SynchronizedTest {
        public static void main(String[] args){ 
            final sTest Test=new sTest();
    
            Thread thread1 = new Thread(new Runnable(){
                @Override
                public void run() {
                    Test.add();
                }
            },"thread1");
    
            Thread thread2 = new Thread(new Runnable(){
                @Override
                public void run() {
                    Test.add2();
                }
            },"thread2");
    
            Thread thread3 = new Thread(new Runnable(){
                @Override
                public void run() {
                    Test.add();
                }
            },"thread3");
    
            Thread thread4 = new Thread(new Runnable(){
                @Override
                public void run() {
                    Test.addX1();
                }
            },"thread4");
    
            thread1.start();
            thread2.start();
            thread3.start();
            thread4.start();
        }
    }

    大致运行结果应该会符合以下说明:
    开头一段是Thread1和Thread4混合交错的输出
    等Thread1输出完毕后是Thread3或者Thread2的输出
    Thread3或者Thread2输出完毕后是Thread2或者Thread3

    以上,也可以自己尝试创建多个sTest 的对象,然后在多个线程中运行不同对象的同一个同步函数。你会发现输出应该是混合交错的,即只会对对象加锁。


    静态方法同步

    静态方法同步是同步在静态方法的类对象(不是类的实例,是指保存类信息的对象)上的,事实上,Java虚拟机中一个类只能对应一个类对象,所以只允许一个线程执行同一个类静态同步方法。其实和实例方法同步是类似的,只不过实例方法同步是在类实例上加锁,静态方法同步是在类对象上加锁。
    示例:

    public class sTest {
        public static synchronized void addJ1(){
            for(int i=400 ;i<500;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
        public static synchronized void addJ2(){
            for(int i=500 ;i<600;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }
    public class SynchronizedTest {
        public static void main(String[] args){ 
            Thread thread1 = new Thread(new Runnable(){
                @Override
                public void run() {
                    sTest.addJ1();
                }
            },"thread1");
    
            Thread thread2 = new Thread(new Runnable(){
                @Override
                public void run() {
                    sTest.addJ2();
                }
            },"thread2");
    
            thread1.start();
            thread2.start();
        }
    }
    

    结果:线程1调用完静态同步函数addJ1后,线程2才会从阻塞中恢复并调用完静态同步函数addJ2
    这里写图片描述


    实例方法中的同步块

    非同步函数里的同步块例子

    public class MyClass {
       public void function(){
          synchronized(X){
              ......
          }
       }
     }

    有时候我们可能只需要给某个函数中的一块代码加同步,这时就可以使用同步块方式实现。在上例中,我么可以看到用括号把一个对象X括了起来,在同步块中,被括号括起来的对象叫做监视对象,即Java会给这个对象X加锁以实现同步。
    一次只有一个线程能够在同步于同一个监视对象的Java方法内执行。
    栗子

    public class sTest {
            //实例方法同步
            public synchronized void add(){
                for(int i=0 ;i<100;i++){
                    System.out.println(Thread.currentThread().getName()+":"+i);
                }
            }
            //实例方法中的同步块
            public void addQ1(){
                synchronized(this){
                    for(int i=600 ;i<700;i++){
                        System.out.println(Thread.currentThread().getName()+":"+i);
                    }
                }
            }
            public void addQ2(){
                synchronized(this){
                    for(int i=700 ;i<800;i++){
                        System.out.println(Thread.currentThread().getName()+":"+i);
                    }
                }
            }
            public void addQ3(String s){
                synchronized(s){
                    for(int i=800 ;i<900;i++){
                        System.out.println(Thread.currentThread().getName()+":"+i);
                    }
                }
            }
            public void addQ4(String s){
                synchronized(s){
                    for(int i=900 ;i<1000;i++){
                        System.out.println(Thread.currentThread().getName()+":"+i);
                    }
                }
            }
    }

    首先我们建两个线程并分别执行addQ1和addQ2

    public static void main(String[] args){ 
            final sTest sTest =new sTest();
            final String s = "1";
            Thread thread1 = new Thread(new Runnable(){
                @Override
                public void run() {
                    sTest.addQ1();
                }
            },"thread1");
    
            Thread thread2 = new Thread(new Runnable(){
                @Override
                public void run() {
                    sTest.addQ2();
                }
            },"thread2");
    
            thread1.start();
            thread2.start();
        }

    结果,因为监视对象为this,即类实例sTest,而thread1和thread2执行的都是同一个对象sTest。所以会出现如下图结果,执行完一个线程的方法前另一个线程会被阻塞。当然,这个栗子其实和实例方法同步里的一样,都是对类实例加锁,也可是尝试在thread2中执行add函数,结果也是会出现阻塞。
    同样的,新建一个String变量s,然后在thread1和thread2中调用addQ3(s)和addQ4(s),也能看到同样的结果。
    这里写图片描述


    静态方法中的同步块

    和实例方法中的同步块是一样的。
    栗子:

    //静态方法同步
    public static synchronized void addJ1(){
                for(int i=400 ;i<500;i++){
                    System.out.println(Thread.currentThread().getName()+":"+i);
                }
            }
    //静态方法中的同步块
    public static void addS1(){
                synchronized(sTest.class){
                    for(int i=1000 ;i<1100;i++){
                        System.out.println(Thread.currentThread().getName()+":"+i);
                    }
                }
            }

    addJ1,addS1这两个方法不允许同时被线程访问。
    与实例方法中的同步块一样,当传入同一个对象时,这两个片段不允许同时被线程访问。

    public static void addS1(String s){
                synchronized(s){
                    for(int i=1000 ;i<1100;i++){
                        System.out.println(Thread.currentThread().getName()+":"+i);
                    }
                }
            }
    public static void addS2(String s){
                synchronized(s){
                    for(int i=1000 ;i<1100;i++){
                        System.out.println(Thread.currentThread().getName()+":"+i);
                    }
                }
            }
    展开全文
  • 前面一篇,我们知道了synchronized...本篇来看看加上synchronized关键字修饰的非静态静态方法的同步锁对象是什么。 1.非静态同步锁对象是this 复制前面一篇代码,修改如下。 package thread; public class...
  • synchronized关键字有两种用法,一种是只用于方法的定义中,另外一种是synchronized块,我们不仅可以使用synchronized来同步一个对象变量,你也可以通synchronized来同步类中的静态方法和非静态方法。那么问题来了,...
  • 静态资源库CDN服务

    千次阅读 2016-01-13 17:43:37
    使用静态资源库可以访问线上资源文件,比如jquery库、bootstrap库。使用百度静态资源库的居多,但是发现百度暂时不支持https协议,bootcdn是一个不错的选择。百度静态资源公共库优点: 稳定,快速 由百度遍布全国...
  • 摘自:http://topmanopensource.iteye.com/blog/1738178 对代码进行同步控制我们可以选择同步方法,也可以选择同步块,这两种方式各有优缺点,至于具体选择什么方式,就见仁见智了,同步块不仅可以更加精确的控制...
  • 但是很多站点针对缓存的策略并不合理,甚至是完全无作为,如果是这样,就完全没有发挥出缓存的优势,而不合理的策略反而很大程度上会导致网站在访问时会发生由于静态资源的竞争关系而导致依赖的静态资源同步的问题...
  • 关于网站静态资源存储OSS操作

    千次阅读 2019-03-06 16:45:45
    需求:网站静态资源太多,CSS,JS,等等,要将这些静态资源转移到OSS中。 问题:某些静态资源是需要随时改变的,所以我们OSS里面的静态资源有些我们要进行实时更新 方法: 将OSS挂载在服务器上,操作步骤: 安装及...
  • 对于Node.js新手,搭建一个静态资源服务器是个不错的锻炼,从最简单的返回文件或错误开始,渐进增强,还可以逐步加深对http的理解。那就开始吧,让我们的双手沾满网络请求! Note: 当然在项目中如果有使用express...
  • 线上服务 静态html CMS 发布rsync 同步

    千次阅读 2016-04-29 10:04:08
    1,静态资源线上服务,有静态的html 比如首页,资讯页面,关于公司,加入我们,帮助页面。 都是静态的html页面。后台写了一个CMS系统,使用velocity 配置模板,然后生成html页面。在同步到线上服务器上面。 主要...
  • 本文基于10*11的太阳同步轨道微纳卫星星座,设计了一套基于星座变化规律进行数传的静态路由方案,以解决数据及时传输的问题。方案基于太阳同步轨道构型及其运行规律,通过分析卫星过境以及交汇情况,将星座分为过境...
  • 我们的静态文件购买了阿里云的NAS。现在我们将文件上传到阿里云的OSS中防止服务中断或者误删除无法恢复。 操作系统: CentOS 7.6 64位软件: ossutil64 使用:wget ...
  • 在项目开发中,网站某些上传的静态资源,如图片、视频等放在服务器Tomcat目录中,会导致项目愈来愈大,下次更新升级会很费劲,如果放在Tomcat目录外面,下次升级静态资源便不用动。 修改Tomcat服务器conf目录下...
  • Vue static 静态资源路径 和 style问题

    千次阅读 2019-06-03 10:58:39
    // 静态资源输出到二级目录下 assetsSubDirectory: ‘static’, // 静态资源cdn地址 assetsPublicPath: ‘/’, ** 引用的时候可直接,不用返回上一级去查找,因为编译输出后的 static 下的资源 跟 html 是在同一个...
  • 使用java搭建了一个web后台 , 现在想用nginx 搭建一个静态资源服务器 。 但是问题来了 :用户是直接将图片上传到tomcat的 , 如何将图片同步到nginx比较好呢? 或者说能不能让用户直接将图片上传到nginx服务器...
  • 欢迎使用Markdown编辑器写博客 本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 ...同步:是所有的操作都做完,才返回给用户结果(某个人做...
  • nginx作为静态资源服务器,重新构建后发生浏览器页面直接取缓存中的js等文件名,但是由于服务器中文件已经被替换导致出现异常。 浏览器在下次请求这个资源的时候不会将请求发向后端,而是直接从缓存中获取资源。 ...
  • 旨在为大家提供更快更多更好的静态资源库的CDN加载库方案! CDN公共库是指将常用的JS库存放在CDN节点,以方便广大开发者直接调用。与将JS库存放在服务器单机上相比,CDN公共库更加稳定、高速。一 般的CDN公共库...
  • 一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用其中的一个synchronized方法了, 其它的线程都只能等待,换句话说...加个普通方法后发现和同步锁无关 换成两个对象后,不是同一把锁了,...
  • 通过tomcat访问静态资源

    千次阅读 2019-07-24 15:33:05
    1.修改tomcat的server.xml文件 访问地址如: ...reloadable="true"表示你修改了jsp文件后不需要重启就可以实现显示的同步,false静态图片等不需要同步的显示 deBug=“0”,tomcat不记录日志
  • 很多情况下往往是静态资源太大,而带宽不足,导致网站加载很慢。 解决方案: 一、 CDN内容分发(解决带宽不足) 使用第三方OOS(对象存储),如七牛云,阿里云OOS等 二、 减少与服务端的带宽传输(解决静态资源太大)...
  • 大公司是怎么发布静态资源

    千次阅读 2016-10-13 13:38:40
    原文地址:...静态资源(Static Resources): js、css、img 等非服务器动态运行生成的文件。 在一般的网站中,静态资源使用频率高,流量占用大。对于有追求
  • 以前一直做系统类项目, 这次突然要做...和单例实现的 在本地PC测试还好 但移动端 换因为机器的好坏 有很大延时, 现在想在游戏开始前 加载静态资源, 不知道加载到哪里合适 如果存 如何取 希望有此经验的朋友 指点 1 2
  • 在开发过程中经常修改一些文件及时部署到测试环境中,比如apache静态资源文件,velocity模板文件等,那么我们可以通过这个eclipse   插件设置好服务器信息,及时将本地修改同步到测试环境中,及时
  • nginx加载静态资源失败原因排查

    千次阅读 2014-05-14 13:29:19
    在今天整体环境上集成测试环境以后,就出现了css找不到的404错误,检查了css文件都在呀,访问路径...于是,我换另外一台服务器(暂且叫B服务器),这个静态资源却能正常显示,所以就从分析这两台服务器(A服务器和B...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 225,671
精华内容 90,268
关键字:

静态资源同步