Java多线程 final和static变量

写了一个多线程中有关final和static的例子,遇到问题了。

 public class MyThread implements Runnable
{
    int i = 0;
    int a = 20;
    static int b = 20;
    static int c = 20;
    static int d = 20;
    final int finalIntNoStatic = a++;
    static int staticInt = b++;
    final int finalInt = c++;
    static final int STATIC_FINAL_INT = d++;

    @Override
    public void run()
    {
        while (i < 10)
        {
            System.out.println("i=" + i + ",finalIntNoStatic=" + finalIntNoStatic + ",a=" + a
                    + ",staticInt=" + staticInt + ",b=" + b + ",finalInt=" + finalInt + ",c=" + c
                    + ",STATIC_FINAL_INT=" + STATIC_FINAL_INT + ",d=" + d);
            i++;
        }
    }
}
 public class MultiThread 
{
    public static void main(String[] args)
    {

        for (int i = 0; i < 5; i++)
        {
            Thread aThread=new Thread(new MyThread());
            aThread.start();
        }
        System.out.println("Run in main thread");
    }
}

最后打印结果为:

 i=0,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=25,STATIC_FINAL_INT=20,d=21
Run in main thread
i=0,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=25,STATIC_FINAL_INT=20,d=21
i=1,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=25,STATIC_FINAL_INT=20,d=21
i=0,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=25,STATIC_FINAL_INT=20,d=21
i=2,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=25,STATIC_FINAL_INT=20,d=21
i=0,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=0,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=25,STATIC_FINAL_INT=20,d=21
i=1,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=25,STATIC_FINAL_INT=20,d=21
i=1,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=25,STATIC_FINAL_INT=20,d=21
i=1,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=3,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=25,STATIC_FINAL_INT=20,d=21
i=1,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=25,STATIC_FINAL_INT=20,d=21
i=4,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=25,STATIC_FINAL_INT=20,d=21
i=2,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=2,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=25,STATIC_FINAL_INT=20,d=21
i=2,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=25,STATIC_FINAL_INT=20,d=21
i=3,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=25,STATIC_FINAL_INT=20,d=21
i=3,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=5,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=25,STATIC_FINAL_INT=20,d=21
i=2,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=25,STATIC_FINAL_INT=20,d=21
i=6,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=25,STATIC_FINAL_INT=20,d=21
i=4,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=4,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=25,STATIC_FINAL_INT=20,d=21
i=3,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=25,STATIC_FINAL_INT=20,d=21
i=5,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=25,STATIC_FINAL_INT=20,d=21
i=5,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=7,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=25,STATIC_FINAL_INT=20,d=21
i=3,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=25,STATIC_FINAL_INT=20,d=21
i=8,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=25,STATIC_FINAL_INT=20,d=21
i=6,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=6,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=25,STATIC_FINAL_INT=20,d=21
i=4,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=25,STATIC_FINAL_INT=20,d=21
i=7,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=25,STATIC_FINAL_INT=20,d=21
i=7,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=9,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=25,STATIC_FINAL_INT=20,d=21
i=4,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=25,STATIC_FINAL_INT=20,d=21
i=8,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=8,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=25,STATIC_FINAL_INT=20,d=21
i=5,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=25,STATIC_FINAL_INT=20,d=21
i=9,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=25,STATIC_FINAL_INT=20,d=21
i=9,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=5,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=25,STATIC_FINAL_INT=20,d=21
i=6,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=25,STATIC_FINAL_INT=20,d=21
i=6,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=25,STATIC_FINAL_INT=20,d=21
i=7,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=25,STATIC_FINAL_INT=20,d=21
i=7,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=25,STATIC_FINAL_INT=20,d=21
i=8,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=25,STATIC_FINAL_INT=20,d=21
i=8,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=25,STATIC_FINAL_INT=20,d=21
i=9,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=25,STATIC_FINAL_INT=20,d=21
i=9,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=25,STATIC_FINAL_INT=20,d=21

我的问题是为什么c的值一直是25,,编译和运行过程中finalInt和c的赋值顺序是怎样的

5个回答

c为什么都是25,因为在main方法中循环只有5次,执行速度非常快,创建了5个MyThread需要的时候可以忽略不计。当创建完后,都还没开始执行子线
程的run方法。但这种结果不是必然的。比如在for循环时,让主线程sleep 100毫秒,你会看到不一样的结果。

     public static void main(String[] args) {
        System.out.println("Run in main thread");
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Run in main thread");
            Thread aThread = new Thread(new MyThread());
            aThread.start();

        }

    }
 Run in main thread
Run in main thread
i=0,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=21,STATIC_FINAL_INT=20,d=21
i=1,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=21,STATIC_FINAL_INT=20,d=21
i=2,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=21,STATIC_FINAL_INT=20,d=21
i=3,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=21,STATIC_FINAL_INT=20,d=21
i=4,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=21,STATIC_FINAL_INT=20,d=21
i=5,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=21,STATIC_FINAL_INT=20,d=21
i=6,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=21,STATIC_FINAL_INT=20,d=21
i=7,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=21,STATIC_FINAL_INT=20,d=21
i=8,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=21,STATIC_FINAL_INT=20,d=21
i=9,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=20,c=21,STATIC_FINAL_INT=20,d=21
Run in main thread
i=0,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=22,STATIC_FINAL_INT=20,d=21
i=1,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=22,STATIC_FINAL_INT=20,d=21
i=2,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=22,STATIC_FINAL_INT=20,d=21
i=3,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=22,STATIC_FINAL_INT=20,d=21
i=4,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=22,STATIC_FINAL_INT=20,d=21
i=5,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=22,STATIC_FINAL_INT=20,d=21
i=6,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=22,STATIC_FINAL_INT=20,d=21
i=7,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=22,STATIC_FINAL_INT=20,d=21
i=8,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=22,STATIC_FINAL_INT=20,d=21
i=9,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=21,c=22,STATIC_FINAL_INT=20,d=21
Run in main thread
i=0,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=23,STATIC_FINAL_INT=20,d=21
i=1,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=23,STATIC_FINAL_INT=20,d=21
i=2,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=23,STATIC_FINAL_INT=20,d=21
i=3,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=23,STATIC_FINAL_INT=20,d=21
i=4,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=23,STATIC_FINAL_INT=20,d=21
i=5,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=23,STATIC_FINAL_INT=20,d=21
i=6,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=23,STATIC_FINAL_INT=20,d=21
i=7,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=23,STATIC_FINAL_INT=20,d=21
i=8,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=23,STATIC_FINAL_INT=20,d=21
i=9,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=22,c=23,STATIC_FINAL_INT=20,d=21
Run in main thread
i=0,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=24,STATIC_FINAL_INT=20,d=21
i=1,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=24,STATIC_FINAL_INT=20,d=21
i=2,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=24,STATIC_FINAL_INT=20,d=21
i=3,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=24,STATIC_FINAL_INT=20,d=21
i=4,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=24,STATIC_FINAL_INT=20,d=21
i=5,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=24,STATIC_FINAL_INT=20,d=21
i=6,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=24,STATIC_FINAL_INT=20,d=21
i=7,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=24,STATIC_FINAL_INT=20,d=21
i=8,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=24,STATIC_FINAL_INT=20,d=21
i=9,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=23,c=24,STATIC_FINAL_INT=20,d=21
Run in main thread
i=0,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=1,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=2,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=3,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=4,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=5,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=6,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=7,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=8,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21
i=9,finalIntNoStatic=20,a=21,staticInt=20,b=21,finalInt=24,c=25,STATIC_FINAL_INT=20,d=21

u013894427
二仪式 麻烦看一下我后面的回答对不对。谢谢。
3 年多之前 回复
u013894427
二仪式 回复wolf犭良: b和d也是静态变量属于类变量,如果b和d不被重新赋值,那么b和d为什么会在每个线程中都保持21,而不是像c一样递增?
3 年多之前 回复
ldz_wolf
wolf犭良 在创建对象的时候就已经对变量进行赋值了,而run方法是要在thread.start()之后才会被调用。c是静态变量属于类变量,在类被第一次调用就会赋值第一次赋值后,后面再创建对象不会 再赋值,而finalInt每次创建对象是都会被创建并赋值
3 年多之前 回复
u013894427
二仪式 没有延时全是25,是否可以理解为函数运行是在赋值之后才运行的。那么第二个问题,c和finalInt的赋值顺序是怎样的,他俩在各个线程中是不同的?
3 年多之前 回复
 static int b=20;
 static int staticInt=b++;
 //相当于
 static int b=20;
 b=b+1;
 static int staticInt=b;
 //b是静态变量属于类变量,所以第二次及之后不会执行 static int b=20;
 //static int staticInt=b++;属于初始化,只会执行一次,所以staticInt的值一直是20;
 //b=b+1属于staticInt的初始化语句,所以之后也不会执行。所以b的值一直是21
ldz_wolf
wolf犭良 是这样的。
3 年多之前 回复
 static int c=20;
 final int staticInt=c++;
 //相当于
 static int c=20;
 c=c+1;
 final int finalInt=c;
 //c是静态变量属于类变量,所以第二次及之后不会执行 static int c=20;
 //finalInt不是静态变量,所以其初始语句会继续执行。
 //final int finalInt=c++;属于初始化,不止执行一次,所以finalInt的值会一直增大;
 //c=c+1属于finalInt的初始化语句,所以会继续执行。所以c的值一直会一直增大;

  static int d=20;
 final static int STATIC_FINAL_INT=d++;
 //相当于
 static int d=20;
 d=d+1;
 final static int STATIC_FINAL_INT=d;
 //d是静态变量属于类变量,所以第二次及之后不会执行 static int c=20;
 //STATIC_FINAL_INT 是静态变量,所以其初始语句不会继续执行。
 //fina staticl int STATIC_FINAL_INT=d++;属于初始化,只执行一次,所以STATIC_FINAL_INT的值不会改变;
 //d=d+1属于STATIC_FINAL_INT的初始化语句,所以不会继续执行。所以d的值不会改变;

更正:d++应该是赋值之后才进行+1操作的。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
java 多线程方法加锁获取自增变量重复问题
/** * 测试多线程并发获取唯一子增长的值 * @author Administrator * */ public class BB { private int increment = 0; final static Set<Integer> set = new HashSet<Integer>(); final static List<Integer> list = new ArrayList<Integer>(); public synchronized int getauto() { return increment++; } public static void main(String[] args) throws Exception { final BB b = new BB(); Vector<Thread> workers = new Vector<Thread>(); for (int i = 0; i < 2; i++) { final Thread t = new Thread(new Runnable() { @Override public void run() { synchronized (this) { for (int j = 0; j < 10000; j++) { int num = b.getauto(); System.out.println(String.valueOf(num)); set.add(num); list.add(num); } } } }); workers.add(t); t.setName("thread-" + i); t.start(); } for (Thread t : workers) { t.join(); } System.out.println("set size :" + set.size()); System.out.println("list size :" + list.size()); } } list和set的size不同
static
在多线程并发的环境下使用static 变量是不安全的,看到很多实例这样使用:private final static ThreadLocal threadlocal=new ThreadLocal();为什么ThreadLocal使用static就没有这个问题呢?还有日志的:private static Logger log=Logger.getLogger(XX.class);
java多线程 参数已经传入构造方法 进入run方法时参数却被改变
请教各位大神:我在for循环里面执行线程,遇到一个问题,代码如下: private static final ExecutorService executors = Executors.newScheduledThreadPool(10); ...... for(...){ executors.execute(new PublishThread(map)); } PublishThread实现了Runnable方法,它有一个私有成员变量map,在PublishThread有一个构造函数,接受了上面的map参数,并将它赋给私有成员变量map。调试的时候发现到构造函数里面时,map值与for循环里面传过来的值是匹配的,但是到run方法里面时,map里面的值却被改变。比如3次for循环传进的参数分别为:{classId=10295, class_ids=[10295, 10325, 10327]},{classId=10292, class_ids=[10292]},{classId=10293, class_ids=[10293]},但是3次run里面看到的值确是{classId=10295,, class_ids=[10293]},{classId=10292,, class_ids=[10293]},{classId=10293,, class_ids=[10293]},这已经不是顺序乱掉的问题(顺序乱本正常),而是变量里面乱了。请问这有可能是什么原因导致的呢?有什么措施可以让这个map不被改变?
java怎么用多线程并发运行for?
如果把下面的改成十个线程并发运行不同的for语句,,就我最下面写好的那个方法,参数用定义好的数组里面的十个int变量,请问要怎么写? ``` public static void main(String[] args) { for(Thread t:getThreads()){ t.start(); } } public static Thread[] getThreads(){ Thread[] thread = new Thread[10]; for(int i=0;i<10;i++){ final Integer num = new Integer(i); thread[i] = new Thread(new Runnable(){ public void run() { int j=5; while(j-->0){ System.out.println("this is thread"+num); } } }); } return thread; } public static void bbq(int a){ for(int b=a;b<a+2;b++){ System.out.println("for循环"+"起始值为"+a+"终止值为"+(a+2)); } } ```
常量池,线程池 什么时候创建什么时候销毁? 有多大?
# 常量池,线程池 什么时候创建什么时候销毁? 有多大? 为什么 内部类访问外部类的对象或是成员变量是必须加上final? 可以再加上static一起修饰码?
log4j2是否存在线程安全问题
应用中定义了一个日志打印切面,切面中定义了一些静态的logger成员变量,类似于这样 private static final Logger logger = LoggerFactory.getLogger(ApiLogAspect.class); 现在的问题是多个线程使用同一个logger是否会存在安全问题。 谢谢各位大佬各显神通
急求java高手,帮忙看下面的游戏代码,为何只能运行界面类然后其他都看不见也不能玩
//子弹Bullet类 package hy; import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; public class Bullet { //坐标 public int x,y; //子弹大小 public int width,height; //子弹杀伤力 public int kill; //速度 public int speed; //子弹图片 public String img; //是否存活 public boolean isLive=true; //子弹类型(好坏) public boolean isGood; public void drawBullet(Graphics g) { Toolkit tk=Toolkit.getDefaultToolkit(); Image img1=tk.getImage(Bullet.class.getClassLoader().getResource("hy.image/"+img)); //画图 g.drawImage(img1, x,y,width,height,null); } } //Person 类 package hy; import java.awt.Graphics; import java.awt.Image; import java.awt.Rectangle; import java.awt.Toolkit; import javax.tools.Tool; public class Person { //敌机坐标 private int x,y; private int width,height; public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public int getHp() { return hp; } public void setHp(int hp) { this.hp = hp; } public int getKill() { return kill; } public void setKill(int kill) { this.kill = kill; } public String getImgurl() { return imgurl; } public void setImgurl(String imgurl) { this.imgurl = imgurl; } public int getSpeed() { return speed; } public void setSpeed(int speed) { this.speed = speed; } //血量 private int hp; public Person(int x, int y, int width, int height, int hp, int kill, String imgurl, int speed) { super(); this.x = x; this.y = y; this.width = width; this.height = height; this.hp = hp; this.kill = kill; this.imgurl = imgurl; this.speed = speed; } //杀伤力 private int kill; //定义图片路径 private String imgurl; //是否存活 public boolean isLive=true; //速度 private int speed; public void drawPerson(Graphics g) { //定义系统工具类 Toolkit tk=Toolkit.getDefaultToolkit(); //创建图片对象 Image img=tk.getImage(Person.class.getClassLoader().getResource("hy.image/"+imgurl)); g.drawImage(img,x,y,width,height,null); move(); } public void move() { y+=speed; if(y>=MyFrame.HEIGHT) { isLive=false; } //捡查子弹是否出屏幕 for (int i = 0; i < MyFrame.bulletAll.size(); i++) { if(MyFrame.bulletAll.get(i).y<0) { MyFrame.bulletAll.get(i).isLive=false; } } this.hitPerson(); this.hitBullet(); } //反回当前敌机的矩形 public Rectangle getPersonRectangle() { return new Rectangle(x,y,width,height); } //判断相撞 public void hitPerson() { //得到敌机矩形 Rectangle personRec=this.getPersonRectangle(); //得到主机矩形 Rectangle myRec=new Rectangle(MyFrame.my_x,MyFrame.my_y,55,60); if(myRec.intersects(personRec)==true) { this.isLive=false; //产生爆炸效果 Explode e=new Explode(x,y); //将e放入爆炸效果集合 MyFrame.explodeAll.add(e); } } //判断和玩家子弹的相撞 public void hitBullet() { //得到敌机矩形 Rectangle personRec=this.getPersonRectangle(); //得到子弹的矩形 for (int i = 0; i < MyFrame.bulletAll.size(); i++) { Rectangle bulletRec=new Rectangle(MyFrame.bulletAll.get(i).x,MyFrame.bulletAll.get(i).y,20,20); if(personRec.intersects(bulletRec)==true) { MyFrame.score+=10; this.isLive=false; //产生爆炸效果 Explode e=new Explode(x,y); //将e放入爆炸效果集合 MyFrame.explodeAll.add(e); } } } } //MyFrame界面类 package hy; import java.awt.Frame; import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.Random; import javax.swing.JFrame; public class MyFrame extends Frame { public static final int WIDTH=900; public static final int HEIGHT=700; public static int my_x=450; public static int my_y=600; //分数 public static int score=0; //定义变量,专门表示键盘按下的键 public static boolean a=false;public static boolean s=false; public static boolean d=false;public static boolean w=false; public static boolean j=false; //敌机的集合 public ArrayList<Person> personAll=new ArrayList<Person>(); //存放爆炸效果的集合 public static ArrayList<Explode> explodeAll=new ArrayList<Explode>(); //存放子弹的集合 public static ArrayList<Bullet> bulletAll=new ArrayList<Bullet>(); public MyFrame() { this.setTitle("雷电飞机射击"+score); this.setSize(WIDTH,HEIGHT); this.setLocationRelativeTo(null); this.setResizable(false); this.addWindowListener(new MyWindowClose()); //添加键盘监听器 this.addKeyListener(new MyKeyDown()); this.setVisible(true); MyThread t=new MyThread(); t.start(); } //定义背景Y座标 int bg_y=0; @Override public void paint(Graphics g) { Toolkit tk=Toolkit.getDefaultToolkit(); Image bg_img=tk.getImage(MyFrame.class.getClassLoader() .getResource("hy.image/bg2.jpg")); g.drawImage(bg_img, 0, bg_y, WIDTH, HEIGHT, null); bg_y+=10; g.drawImage(bg_img, 0, -HEIGHT+bg_y, WIDTH, HEIGHT, null); //判断bg_y的值是否超过窗体的高度 if(bg_y>HEIGHT) { bg_y=0; } Image my_img=tk.getImage(MyFrame.class.getClassLoader() .getResource("hy.image/my_img.jpg")); g.drawImage(my_img, my_x, my_y, 55, 60, null); //创建随机对象 Random rd=new Random(); if(rd.nextInt(10)==5) { //创建敌机 Person person=new Person(rd.nextInt(850), 45, 32, 58, 100, 100, "enemy1.jpg", 15); personAll.add(person); } for (int i = 0; i < personAll.size(); i++) { Person person=personAll.get(i); if(person.isLive) { person.drawPerson(g); } else personAll.remove(person); } //绘画爆炸 for (int i = 0; i < explodeAll.size(); i++) { Explode e=explodeAll.get(i); //判断是否是活字弹 if(e.isLive) { e.drawExplode(g); } else { explodeAll.remove(e); } } //绘画子弹 for (int i = 0; i < bulletAll.size(); i++) { Bullet bullet=bulletAll.get(i); //判断是否是活子弹 if(bullet.isLive) { bullet.drawBullet(g); } else { bulletAll.remove(bullet); } } this.setTitle("雷电飞机射击游戏 分数:"+score); } public void move() { if(a) MyFrame.my_x-=20; if(d) MyFrame.my_x+=20; if(s) MyFrame.my_y+=20; if(w) MyFrame.my_y-=20; if(j) { Fire(); } } //开火方法 public void Fire() { Bullet bullet=new Bullet(); bullet.x=my_x+22; bullet.y=my_y+30; bullet.img="bullet.jpg"; bullet.speed=40; bullet.width=20; bullet.height=20; bulletAll.add(bullet); } Image img=null; @Override public void update(Graphics g) { if(img==null) { img=this.createImage(WIDTH, HEIGHT); } //利用img创建虚拟画笔 Graphics gb=img.getGraphics(); //调用paint方法 paint(gb); //利用真实的画笔g来画图片 g.drawImage(img, 0,0,WIDTH,HEIGHT,null); } public static void main(String[] args) { new MyFrame(); } //内部类,线程类,用来刷新当前窗体S class MyThread extends Thread { @Override public void run() { while(true) { repaint(); //每时每刻都判断是否要移动飞机 move(); try { //让子弹前进,速度要比玩家速度快很多 for (int i = 0; i < bulletAll.size(); i++) { Bullet bullet=bulletAll.get(i); bullet.y-=bullet.speed; } Thread.sleep(65); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } //MyWindowClose类 package hy; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; class MyWindowClose extends WindowAdapter { @Override public void windowClosing(WindowEvent e) { System.exit(0); } } class MyKeyDown extends KeyAdapter { @Override public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_A: MyFrame.a=true; break; case KeyEvent.VK_S: MyFrame.s=true; break; case KeyEvent.VK_D: MyFrame.d=true; break; case KeyEvent.VK_W: MyFrame.w=true; break; case KeyEvent.VK_J: MyFrame.j=true; break; default: break; } } @Override public void keyReleased(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_A: MyFrame.a=false; break; case KeyEvent.VK_S: MyFrame.s=false; break; case KeyEvent.VK_D: MyFrame.d=false; break; case KeyEvent.VK_W: MyFrame.w=false; break; case KeyEvent.VK_J: MyFrame.j=false; break; default: break; } } } //Explode爆炸类 package hy; import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; public class Explode { //坐标 private int x; private int y; //定义爆炸显示的图片 String img[]={"boom1.jpg","boom2.jpg","boom3.jpg","boom4.jpg","boom5.jpg","boom6.jpg","boom7.jpg","boom8.jpg","boom9.jpg"}; //爆炸的生命 public boolean isLive=true; //定义下标 private int index=0; public Explode(int x, int y) { this.x = x; this.y = y; index++; } public void drawExplode(Graphics g) { //得到工具类 Toolkit tkToolkit=Toolkit.getDefaultToolkit(); //得到图片对象 //得到数组中的图片 String image=img[index]; Image img1=tkToolkit.getImage(Explode.class.getClassLoader().getResource("hy.image/"+image)); g.drawImage(img1, x,y,null); index++; if(index>=img.length) { index=0; //生命消失 isLive=false; } } } //Sound背景音乐类 package hy; import java.applet.AudioClip; import java.io.*; import java.applet.Applet; import javax.swing.JFrame; import java.net.MalformedURLException; import java.net.URL; public class Sound extends JFrame{ public Sound(){ super(); } public static void main(String args[]) { try { URL cb; File f = new File("hy.music\\t.wav"); //引号里面的是音乐文件所在的绝对路径 cb = f.toURL(); AudioClip aau; aau = Applet.newAudioClip(cb); //aau.play(); aau.loop(); //循环播放 aau.play() 单曲 aau.stop()停止播放 Sound frame=new Sound(); //frame.setBounds(0, 0, 300, 200); //frame.setVisible(true); } catch (MalformedURLException e) { e.printStackTrace(); } } }
从任何类中都能获取request中的属性,只能用线程局部变量吗?
web应用中实现国际化,基于request.getLocale获取请求者的国家语言,所以很多类中都会用到: ResourceBundle messages = ResourceBundle.getBundle("message",locale); 来获取适当的资源文件,因此需要在所有类中都能取到request中的locale属性。 我可以创建一个线程局部变量来存放它,如: public class I18nUnit { private static final ThreadLocal<String> locale = new ThreadLocal<String>(); ...... public static String getLocale() { if (locale.get() == null) { return ""; } return (String) locale.get(); } } 在servlet的doService方法开头设置这个变量,然后在任意类中用I18nUnit.getLocale()获取,能够实现。 但我觉得这个办法挺另类挺绕的,应该有更容易的获取方式吧? [b]问题补充:[/b] lovewhzlq:那么在任意类中如何获取session呢?我原来都是request.getSession(),任意类中如果取不到request,session也得不到啊 [b]问题补充:[/b] bohemia: 有些普通类中要抛出异常,异常消息需要是国际化的,抛出后是要展示给用户看的,您认为有其它方法可以解决吗?
关于ThreadLocal内存泄漏
看到很多说ThreadLocal内存泄漏的都是把ThreadLocal变量置为null后说value一直存在 ,造成内存泄漏。那么再利用线程池的环境中,如果把ThreadLocal变量声明为static final的,是不是一定不会发生内存泄漏的可能了?或者说对于一个线程来说,ThreadLocalMap中最多有一条关于这个ThreadLocal变量的记录? 因为即使线程不死亡一直存在,但是map里的key是一样的,所以set方法只是在覆盖旧值?
Hibernate中的session的save方法。
我正在学习hibernate框架,然后在做一个插入的时候遇到了一个问题。通过跟踪我发现在执行session.save(obj);方法时,程序就不动了。并且在获取session时还打印出下面红色的信息。 请问一个是什么原因以及怎么解决呢? ![图片说明](https://img-ask.csdn.net/upload/201604/30/1462019362_918790.png) ``` public int insertClient(Client client) { // TODO Auto-generated method stub //HibernateUtil.closeSession(); System.out.println("client insert1 :"); Session session = HibernateUtil.currentSession(); //System.out.println(session); System.out.println("client insert2 :"); Transaction transaction = session.beginTransaction(); System.out.println("client insert3 :"); System.out.println(client); Integer s= (Integer) session.save(client); System.out.println("client insert4 :"+s); try { transaction.commit(); } catch (Exception e) { transaction.rollback(); } finally { HibernateUtil.closeSession(); } System.out.println("row :"+s); return s; } ``` ``` public class HibernateUtil { public static final SessionFactory sessionFactory; static { try { // 使用默认的hibernate.cfg.xml配置文件创建Configuration实例 Configuration cfg = new Configuration() .configure(); // 以Configuration实例来创建SessionFactory实例 ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(cfg.getProperties()).build(); sessionFactory = cfg.buildSessionFactory(serviceRegistry); } catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } // ThreadLocal可以隔离多个线程的数据共享,因此不再需要对线程同步 public static final ThreadLocal<Session> session = new ThreadLocal<Session>(); public static Session currentSession() throws HibernateException { Session s = session.get(); System.out.println("session get:"); // 如果该线程还没有Session,则创建一个新的Session if (s == null) { s = sessionFactory.openSession(); // 将获得的Session变量存储在ThreadLocal变量session里 session.set(s); } return s; } public static void closeSession() throws HibernateException { Session s = session.get(); if (s != null) s.close(); session.set(null); } } ```
“构造一个虚拟位置信息给谷歌地图,让其定位错误”失败
用以下代码“构造一个虚拟位置信息给谷歌地图,让其定位错误”无法实现,给位大神指点迷津,小弟开始研究Android编程不久,有点小白望谅解 正常情况下是:在本应用横纵有一个数据库,记录用户对不同需要获取位置信息的应用按精确度进行分类,分别为城镇级,精确级,街道级,不同级别对应的位置模糊程度不同,虚构的位置信息也不同 代码如下: package com.example.hermit; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Random; import android.app.ActivityManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.ComponentName; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.database.Cursor; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.util.Log; import android.widget.Toast; public class service extends Service { LocationManager locationManager; private PackageManager pm;// Package Manager(包管理)-用来找到关于安装在设备上的应用程序包的相关信息。 private ArrayList<String> default1 = new ArrayList<String>();// 城镇;创建default1来保存字符串数组 private ArrayList<String> default2 = new ArrayList<String>();// 街道;创建default2来保存字符串数组 private ArrayList<String> default3 = new ArrayList<String>();// 精准;创建default3来保存字符串数组 private ArrayList<String> user1 = new ArrayList<String>();// 城镇 private ArrayList<String> user2 = new ArrayList<String>();// 街道 private ArrayList<String> user3 = new ArrayList<String>();// 精准 private Strategy_DB DB = new Strategy_DB(this); double test1; private String mocLocationProvider; private String currentProvider; private String Provider; // Android的location定义新的变量 private Location currentLocation; Location LOCtmp; Location Location; Location Loc; Location l; // 精确 double latitude;// 经度 double longitude;// 纬度 // 城镇 double latitude1; double longitude1; // 街道 double latitude2; double longitude2; double ltd_tmp; double lng_tmp; private String AN; private String TAG = "service"; static final int DELAY = 4000; // 相当于定义常量DELAY String name; int flag = 0; static final String ACTION_FOREGROUND = "com.example.android.apis.FOREGROUND"; static final String ACTION_BACKGROUND = "com.example.android.apis.BACKGROUND"; private final IBinder mBinder = new localBinder(); /* * Handler在android里负责发送和处理消息。它的主要用途有:   1)按计划发送消息或执行某个Runnanble(使用POST方法); *   2)从其他线程中发送来的消息放入消息队列中,避免线程冲突(常见于更新UI线程)/用来向不属于自己的线程的队列中加入某个动作 */ Handler handler; Runnable runnable; private static final Class<?>[] mSetForegroundSignature = new Class[] { boolean.class }; private static final Class<?>[] mStartForegroundSignature = new Class[] { int.class, Notification.class }; private static final Class<?>[] mStopForegroundSignature = new Class[] { boolean.class }; private NotificationManager mNM; private Method mSetForeground; private Method mStartForeground; private Method mStopForeground; private Object[] mSetForegroundArgs = new Object[1]; private Object[] mStartForegroundArgs = new Object[2]; private Object[] mStopForegroundArgs = new Object[1]; /* *  可以看出,对于一个对象的方法调用来说,如果这个方法能够被分派出去, * 如上面的“hello”方法,可以在InvokeTestor1类中找到,就被分派给InvokeTestor1类的“hello”方法; * 如果不能被分派,如上面的“foo”方法,则调用“invokeMethod”方法 */ void invokeMethod(Method method, Object[] args) { try { method.invoke(this, args); } catch (InvocationTargetException e) { // Should not happen. Log.w("ApiDemos", "Unable to invoke method", e); } catch (IllegalAccessException e) { // Should not happen. Log.w("ApiDemos", "Unable to invoke method", e); } } /** * This is a wrapper around the new startForeground method, using the older * APIs if it is not available. */ void startForegroundCompat(int id, Notification notification) { // If we have the new startForeground API, then use it. if (mStartForeground != null) { mStartForegroundArgs[0] = Integer.valueOf(id); mStartForegroundArgs[1] = notification; Log.d(TAG, "Updater running"); invokeMethod(mStartForeground, mStartForegroundArgs); return; } // Fall back on the old API. mSetForegroundArgs[0] = Boolean.TRUE; Log.d(TAG, "Updater sdsf"); invokeMethod(mSetForeground, mSetForegroundArgs); mNM.notify(id, notification); } /** * This is a wrapper around the new stopForeground method, using the older * APIs if it is not available. */ void stopForegroundCompat(int id) { // If we have the new stopForeground API, then use it. if (mStopForeground != null) { mStopForegroundArgs[0] = Boolean.TRUE; invokeMethod(mStopForeground, mStopForegroundArgs); return; } // Fall back on the old API. Note to cancel BEFORE changing the // foreground state, since we could be killed at that point. mNM.cancel(id); mSetForegroundArgs[0] = Boolean.FALSE; invokeMethod(mSetForeground, mSetForegroundArgs); } public class localBinder extends Binder { service getService() { return service.this; } } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub Log.i(TAG, "this is on binder"); return null; } public void OnCreate() { // 获得系统级的服务Notification Manager,调用getSystemService()方法实现 mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); // 为了兼容Android1的代码。即如果mStartForeground / mStopForeground // 为空就表示是Android1的环境。 try { mStartForeground = getClass().getMethod("startForeground", mStartForegroundSignature); mStopForeground = getClass().getMethod("stopForeground", mStopForegroundSignature); return; } catch (NoSuchMethodException e) { // Running on an older platform. mStartForeground = mStopForeground = null; } try { mSetForeground = getClass().getMethod("setForeground", mSetForegroundSignature); } catch (NoSuchMethodException e) { // 抛出一个异常 throw new IllegalStateException( "OS doesn't have Service.startForeground OR Service.setForeground!"); } } public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "recived start id" + startId + ":" + intent); // //获得系统级的服务Location Manager,调用getSystemService()方法实现 locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); // mocLocationProvider 存放gps信息 mocLocationProvider = LocationManager.GPS_PROVIDER; // 根据设置的Criteria对象,获取最符合此标准的provider对象 currentProvider = locationManager.getProvider( LocationManager.GPS_PROVIDER).getName(); // 获取网络位置信息 Provider = locationManager .getProvider(LocationManager.NETWORK_PROVIDER).getName(); // 根据当前provider对象获取最后一次位置信息 l = locationManager.getLastKnownLocation(Provider); latitude = l.getLatitude();// 精确 longitude = l.getLongitude(); chose(); if (flag == 1) { ltd_tmp = latitude1;// 城镇 lng_tmp = longitude1; } if (flag == 2) { ltd_tmp = latitude2;// 街道 lng_tmp = longitude2; } if (flag == 3) { ltd_tmp = latitude;// 精确 lng_tmp = longitude; } if (flag == 0) { ltd_tmp = latitude1;// 精确 lng_tmp = longitude1; } //创建 一个 “用于模拟的坐标提供者” // 创建一个仿真位置信息并添加到当前正在运行的provider中 locationManager.addTestProvider(mocLocationProvider, false, false, false, false, false, false, false, 0, 5); // 让创建好的仿真位置信息对于正在运行的provider可用。并且该值会替代原有真实provider中的数据 locationManager.setTestProviderEnabled(mocLocationProvider, true); Location = new Location(mocLocationProvider); // Location.setTime(currentLocation.getTime() ); // Location.setLatitude(Loc.getLatitude()); // Location.setLongitude(Loc.getLongitude()); float x = 5.0f, y = 0.0f, s = 10.0f; Location.setAccuracy(x);// 设置精度 Location.setSpeed(s); Location.setAltitude(y);// 设置 // Log.e("location", Location.toString()); // 获得已安装的应用程序信息 。可以通过getPackageManager()方法获得 pm = getPackageManager(); // 通过系统服务获取ActivityManager ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); // 获得当前正在运行的activity ComponentName cn = am.getRunningTasks(1).get(0).topActivity; name = cn.getPackageName(); // 在android中提供了一种异步回调机制Handler,使用它,我们可以在完成一个很长时间的任务后做出相应的通知。 handler = new Handler(); // 实现多线程 runnable = new Runnable() { public void run() { DB.closeDB();// 关闭数据库 DB.openDB();// 打开数据库 opDB(); ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); ComponentName cn2 = am.getRunningTasks(1).get(0).topActivity; String cmp = cn2.getPackageName(); // Log.d(TAG, "Updater running"); if (!name.equals(cmp) && cmp.equals("com.example.hermit")) { name = cmp; } if (!name.equals(cmp) && !cmp.equals("com.android.launcher") && !cmp.equals("com.example.hermit")) { Log.d(TAG, cmp); try { ApplicationInfo info = pm.getApplicationInfo(cmp, 0); AN = (String) pm.getApplicationLabel(info);// AN表示获取的应用标签 Log.i("AN", AN); } catch (NameNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } chose(); if (flag == 1) { ltd_tmp = latitude1;// 城镇 lng_tmp = longitude1; } if (flag == 2) { ltd_tmp = latitude2;// 街道 lng_tmp = longitude2; } if (flag == 3) { ltd_tmp = latitude;// 精确 lng_tmp = longitude; } if (flag == 0) { ltd_tmp = latitude1;// 精确 lng_tmp = longitude1; } Location.setTime(System.currentTimeMillis()); Location.setLatitude(ltd_tmp); Location.setLongitude(lng_tmp); //locationManager.setTestProviderLocation(mocLocationProvider, Location); Log.e("l", l.toString()); Log.i("test1", "lat long" + latitude + longitude); Log.i("location", Location.toString()); Log.i("location", "flag=" + flag + " " + ltd_tmp + lng_tmp); try { locationManager.setTestProviderLocation( mocLocationProvider, Location); } catch (IllegalArgumentException e) { Log.d("test", "location error"); String mess = e.getLocalizedMessage(); Log.d("test", mess); } locationManager.requestLocationUpdates(currentProvider, 0, 0, locationListener); currentLocation = locationManager .getLastKnownLocation(currentProvider); if (currentLocation == null) { // Log.d("test","location error"); locationManager.requestLocationUpdates(currentProvider, 0, 0, locationListener); currentLocation = locationManager .getLastKnownLocation(currentProvider); } else { // Log.e("location", currentLocation.toString()); } // 获取当前运行的activity并放于cn2中 // ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); // ComponentName cn2 = am.getRunningTasks(1).get(0).topActivity; // String cmp = cn2.getPackageName(); // // // Log.d(TAG, "Updater running"); // if (!name.equals(cmp) && cmp.equals("com.example.hermit")) { // name = cmp; // } // if (!name.equals(cmp) && !cmp.equals("com.android.launcher") // && !cmp.equals("com.example.hermit")) { // Log.d(TAG, cmp); // try { // ApplicationInfo info = pm.getApplicationInfo(cmp, 0); // AN = (String) pm.getApplicationLabel(info);// AN表示获取的应用标签 // Log.i("AN", AN); // } catch (NameNotFoundException e1) { // // TODO Auto-generated catch block // e1.printStackTrace(); // } Log.d("falg", "flag=" + flag); // chose(); // if (flag == 1) { // ltd_tmp = latitude1;// 城镇 // lng_tmp = longitude1; // } // if (flag == 2) { // ltd_tmp = latitude2;// 街道 // lng_tmp = longitude2; // } // if (flag == 3) { // ltd_tmp = latitude;// 精确 // lng_tmp = longitude; // } // if (flag == 0) { // ltd_tmp = latitude1;// 精确 // lng_tmp = longitude1; // } // Location.setTime(System.currentTimeMillis()); // Location.setLatitude(ltd_tmp); // Location.setLongitude(lng_tmp); // locationManager.setTestProviderLocation(mocLocationProvider, Location); // 监听到用户打开了需要访问位置信息的应用 Log.d("falg", "flag=" + flag); if (flag == 1) { Intent i = new Intent(service.this, Dialog.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Bundle b = new Bundle(); b.putString("textview", "粒度策略:城镇级 "); i.putExtras(b); startActivity(i); flag = 0; } if (flag == 2) { Intent i = new Intent(service.this, Dialog.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Bundle b = new Bundle(); b.putString("textview", "粒度策略:街道级 "); i.putExtras(b); startActivity(i); flag = 0; } if (flag == 3) { Intent i = new Intent(service.this, Dialog.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Bundle b = new Bundle(); b.putString("textview", "粒度策略:精确级 "); i.putExtras(b); startActivity(i); flag = 0; } name = cmp; } handler.postDelayed(this, 3000); } }; handler.postDelayed(runnable, 3000); handleCommand(intent); // new ClientThread().run(); return START_STICKY; } private void chose() { double x1, y1, x2, y2; Random rdr = new Random();// rdr为一组随机数流 Random rdz = new Random(); int Z = rdz.nextInt(360);// 随机数的生成范围小于360 double R2 = 1 + rdr.nextDouble() * 10;// x2街道 double R1 = 9 + rdr.nextDouble() * 20;// x1城镇 if (Z <= 90 && Z >= 0) { x1 = R1 * Math.sin(Z * Math.PI / 180);// (Z*Math.PI/180)为弧度制 y1 = R1 * Math.cos(Z * Math.PI / 180); x2 = R2 * Math.sin(Z * Math.PI / 180); y2 = R2 * Math.cos(Z * Math.PI / 180); } else if (Z <= 180 && Z > 90) { x1 = R1 * Math.cos((Z - 90) * Math.PI / 180); y1 = R1 * Math.sin((Z - 90) * Math.PI / 180) * -1; x2 = R2 * Math.cos((Z - 90) * Math.PI / 180); y2 = R2 * Math.sin((Z - 90) * Math.PI / 180) * -1; } else if (Z <= 270 && Z > 180) { x1 = R1 * Math.sin((Z - 180) * Math.PI / 180) * -1; y1 = R1 * Math.cos((Z - 180) * Math.PI / 180) * -1; x2 = R2 * Math.sin((Z - 180) * Math.PI / 180) * -1; y2 = R2 * Math.cos((Z - 180) * Math.PI / 180) * -1; } else { x1 = R1 * Math.cos((Z - 270) * Math.PI / 180) * -1; y1 = R1 * Math.sin((Z - 270) * Math.PI / 180); x2 = R2 * Math.cos((Z - 270) * Math.PI / 180) * -1; y2 = R2 * Math.sin((Z - 270) * Math.PI / 180); } Log.i("r", "R1=" + R1 + "R2=" + R2); Log.i("x1= y1=", "x1=" + x1 + "y1=" + y1);// 城镇 Log.i("x2= y2=", "x2=" + x2 + "y2=" + y2); // latitude=location.getLatitude();//精确 // longitude=location.getLongitude(); latitude1 = latitude + x1 / 111;// 城镇 longitude1 = longitude + y1 / (111 * Math.cos(Z * Math.PI / 180)); latitude2 = latitude + x2 / 111;// 街道 longitude2 = longitude + y2 / (111 * Math.cos(Z * Math.PI / 180)); // location1.setLatitude(latitude1);//城镇 // location1.setLongitude(longitude1); // // location2.setLatitude(latitude2);//街道 // location2.setLongitude(longitude2); // Log.d("test1111","哈哈"); if (user1.contains(AN) == true) {// 如果应用在用户城镇级 flag = 1; // Log.d("test222","哈哈"); } else { if (user2.contains(AN) == true) flag = 2;// 如果应用在用户街道级 else { if (user3.contains(AN) == true) flag = 3;// 如果应用在用户精确级 else { if (default1.contains(AN) == true) { Log.d("默认城镇级", "哈哈"); flag = 1; } else { if (default2.contains(AN) == true) { Log.d("默认街道级", "哈哈"); flag = 2; } else { if (default3.contains(AN) == true) { Log.d("默认精确级", "哈哈"); flag = 3; } else { flag = 0; } } } } } } } private LocationListener locationListener = new LocationListener() { // 位置发生改变时调用 @Override public void onLocationChanged(Location location) { Log.d("Location", "onLocationChanged"); // handler.removeCallbacks(runnable); } // provider失效时调用 @Override public void onProviderDisabled(String provider) { Log.d("Location", "onProviderdisabled"); } // provider启用时调用 @Override public void onProviderEnabled(String provider) { Log.d("Location", "onProviderEnabled"); Location.setLatitude(ltd_tmp); Location.setLongitude(lng_tmp); } // 状态改变时调用 @Override public void onStatusChanged(String provider, int status, Bundle extras) { Log.d("Location", "onStatusChanged"); Location.setLatitude(ltd_tmp); Location.setLongitude(lng_tmp); } }; void handleCommand(Intent intent) { if (service.ACTION_FOREGROUND.equals(intent.getAction())) { // In this sample, we'll use the same text for the ticker and the // expanded notification CharSequence text = getText(R.string.foreground_service_started); // Set the icon, scrolling text and timestamp Notification notification = new Notification( R.drawable.ic_launcher, text, System.currentTimeMillis()); // The PendingIntent to launch our activity if the user selects this // notification // 用户点击service的通知时返回到主界面 PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, TownactivityActivity.class), 0); // Set the info for the views that show in the notification panel. notification.setLatestEventInfo(this, getText(R.string.local_service_label), text, contentIntent); startForeground(1000, notification); // startForegroundCompat(R.string.foreground_service_started, // notification); } else if (service.ACTION_BACKGROUND.equals(intent.getAction())) { stopForegroundCompat(R.string.foreground_service_started); } } public void onDestroy() { Log.i(TAG, "this is ondestroy"); handler.removeCallbacks(runnable); Toast.makeText(this, "service stopped", Toast.LENGTH_SHORT).show(); } public boolean onUnbind(Intent intent) { Log.i(TAG, "this is onUnbind"); return super.onUnbind(intent); } private void opDB() { // 清空所有元素 user1.clear(); user2.clear(); user3.clear(); default1.clear(); default2.clear(); default3.clear(); // Log.d("1","test"); Cursor tmp1 = DB.select("USER1"); Cursor tmp2 = DB.select("USER2"); Cursor tmp3 = DB.select("USER3"); // Log.d("1","test"); if (tmp1.moveToFirst() == false) ; else { String T1 = tmp1.getString(1); if (user1.contains(T1) == true) ; else user1.add(T1); while (tmp1.moveToNext()) { T1 = tmp1.getString(1); if (user1.contains(T1) == true) ; else user1.add(T1); // Log.d("test",T1); } } if (tmp2.moveToFirst() == false) ; else { String T2 = tmp2.getString(1); if (user2.contains(T2) == true) ; else user2.add(T2); while (tmp2.moveToNext()) { T2 = tmp2.getString(1); if (user2.contains(T2) == true) ; else user2.add(T2); // Log.d("test",T2); } } if (tmp3.moveToFirst() == false) ; else { String T3 = tmp3.getString(1); if (user3.contains(T3) == true) ; else user3.add(T3); while (tmp3.moveToNext()) { T3 = tmp3.getString(1); if (user3.contains(T3) == true) ; else user3.add(T3); // Log.d("test",T3); } } } }
关于iterator的成员遍历问题
我写了服务器端和客户端的程序,我想是实现客户之间发送群组消息,所以我在服务器端定义全局变量在线组员集合,然后在服务器主类构造方法实例化了在线组员集合,然后定义一个群组消息发送方法,但是发现遍历不成功,跳出了while语句,it.hasNext()竟然为false 客户端的代码应该是没问题的,就是 使用使用线程去接收服务器端的消息 新人一枚 求求大神指教一下 代码如下 public class GroupServer { private static Set<Socket> Members; private int port=8008; private ServerSocket serverSocket; private ExecutorService executorService; //线程池 private final int POOL_SIZE=15; //单个CPU时线程池中工作线程的数目 public GroupServer() throws IOException { serverSocket = new ServerSocket(port);//打开服务器端口 //创建线程池 //Runtime的availableProcessors()方法返回当前系统的CPU的数目 //系统的CPU越多,线程池中工作线程的数目也应该越多 executorService= Executors.newFixedThreadPool( Runtime.getRuntime().availableProcessors() * POOL_SIZE); Members=new HashSet<Socket> (); System.out.println("多用户服务器启动"); } public void service() { while (true) { Socket socket=null; try { socket = serverSocket.accept(); //监听客户请求, 阻塞语句. //接受一个客户请求,从线程池中拿出一个线程专门处理该客户. executorService.execute(new Handler(socket)); }catch (IOException e) { } } } public static void sendToAllMembers(String msg)throws IOException{ PrintWriter pw; Socket tempSocket; OutputStream out; Iterator it=Members.iterator(); while(it.hasNext()){//遍历在线成员set集合. System.out.println("socketTCP.GroupServer.sendToAllMembers()"); tempSocket=(Socket) it.next(); //取出一个成员 out =tempSocket.getOutputStream();//得到输出流 //装饰成字符流 pw=new PrintWriter(new OutputStreamWriter(out,"GB2312"),true); System.out.println("socketTCP.GroupServer.sendToAllMembers()"); pw.println(msg);//发送聊天信息给成员 }//end while群组发送结束。 } public static void removeMember(Socket socket){ Members.remove(socket);//删除一个成员 } class Handler implements Runnable{ private Socket socket; public Handler(Socket socket){ this.socket=socket; } private PrintWriter getWriter(Socket socket)throws IOException{ OutputStream socketOut = socket.getOutputStream(); return new PrintWriter(new OutputStreamWriter(socketOut,"GB2312"),true); } private BufferedReader getReader(Socket socket)throws IOException{ InputStream socketIn = socket.getInputStream(); return new BufferedReader(new InputStreamReader(socketIn,"GB2312")); } public void run(){//覆盖线程体 try { System.out.println("New connection accepted " +socket.getInetAddress()); BufferedReader br =getReader(socket);//字节装饰成字符流 PrintWriter pw = getWriter(socket); //字节装饰成字符流 String msg = null; while ((msg = br.readLine()) != null) { sendToAllMembers(msg); pw.println("From ThreadServer: "+msg);//send to client. if (msg.contains("bye".subSequence(0, 2))){ System.out.println( socket.getInetAddress() + ":" +"Exit"); break; } } }catch (IOException e) { e.printStackTrace(); }finally { try{ if(socket!=null)socket.close(); }catch (IOException e) { } } } } public static void main(String args[])throws IOException { new GroupServer().service(); } }
Servlet实现排队处理视频转换请求中的疑问,贴代码请斧正!
项目需求:客户端上传视频(*.avi),server将请求排队,然后一个一个排队处理转换任务. 前面问过该问题,现在自己实现,由于多线程不精通. 如下实现该排队需求,自己感觉不太准确,有问题,请指出,并给个解决方法. (tip,没有servlet的单线程模式或将dopost方法synchronied,视乎这样做是由系统将请求排队,request请求不能立即得到回复! :) ) 1.TaskBean 写了一个bean,这个bean用来存储了转换任务的属性. [code="java"]package videoconvert; public class TaskBean { private String videoPath; private String flvPath; private boolean isConverting; public String getVideoPath() { return videoPath; } public void setVideoPath(String videoPath) { this.videoPath = videoPath; } public String getFlvPath() { return flvPath; } public void setFlvPath(String flvPath) { this.flvPath = flvPath; } public boolean getIsConverting() { return isConverting; } public void setIsConverting(boolean isConverting) { this.isConverting = isConverting; } }[/code] 2.VideoConvert 这是个servlet,用来排队请求,并调度转换工具进行转换. [code="java"]package videoconvert; import java.io.IOException; import java.io.PrintWriter; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class VideoConvert extends HttpServlet { private static final long serialVersionUID = 6312986385178354217L; private static Logger logger = LoggerFactory.getLogger(VideoConvert.class); private static LinkedList<TaskBean> taskStack = new LinkedList<TaskBean>(); public VideoConvert() { super(); } @Override public void init() throws ServletException { // TODO Auto-generated method stub super.init(); new Timer().schedule(new TimerTask() { public void run() { checkTaskList();[color=red]//这里按时间间隔检查栈.并取出task来执行.[/color] } }, 0, 10000); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (request.getRemoteAddr().equals("127.0.0.1")) { TaskBean task = new TaskBean(); String videoPath = (String) request.getAttribute("VideoPath"); String flvPath = (String) request.getAttribute("FlvPath"); if (null != videoPath && null != flvPath) { task.setVideoPath(videoPath); task.setFlvPath(flvPath); task.setIsConverting(false); synchronized (taskStack) { [color=red] //多线程以taskStack栈作为同步量,当持有taskStack对象才添加任务进栈[/color] taskStack.addLast(task); logger.info("add task to queue!"); } } else { logger.info("the paramters are null!"); } } else { logger.info("visit is illegal!"); } response.setContentType("text/html; charset=UTF-8"); PrintWriter pw = response.getWriter(); pw.write("上传视频成功,等待转换....") pw.flush(); } //这个是timer触发的任务,取出stack中的一个任务,然后检查是否在转换中,如果没有就调用工具进行转换. private void checkTaskList() { synchronized (taskStack) { [color=red]//这里感觉不准确,因为同步块里面,Timer新建的了一个线程p1来调用外 //部工具 // FFmpeg.并且会(process.waitFor();)等待FFmepg运行完成来返回结果. 所以在调 // 用外部工具的整个过程都占用了同步量(taskStack).所以应该如何改进...[/color] TaskBean task = taskStack.peekFirst(); if (null != task) { if (!task.getIsConverting()) { task.setIsConverting(true); executProcess(task); } } } } private void executProcess(TaskBean task) { MediaUtility mu = new MediaUtility(); //在类MediaUtility 中调用新建线程调用工具,并waitfor()结果 if (mu.video2Flv(task.getVideoPath(), task.getFlvPath())) { taskStack.removeFirst(); logger.info("achieve video convert,removeFirst task!"); } else { logger.error("video convert fail!"); taskStack.removeFirst(); } } }[/code] 3.调用工具的类 MediaUtility [code="java"]package videoconvert; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MediaUtility { private static Logger logger = LoggerFactory.getLogger(MediaUtility.class); public boolean video2Flv(String videoPath, String flvPath) { if (!checkfile(videoPath)) { logger.error(videoPath + " is not file!"); return false; } String cmdStr = "ffmpeg -i " + videoPath + " " + flvPath; logger.info(cmdStr); logger.info("Starting convert video to flv...."); BufferedReader ffmpegOut = null; try { Process process = Runtime.getRuntime().exec(cmdStr); // ffmpegOut = new BufferedReader(new InputStreamReader(process // .getInputStream())); ffmpegOut = new BufferedReader(new InputStreamReader(process .getErrorStream())); // FileWriter fileOut = new FileWriter(new File("c:/F.txt")); String dLine = ""; while ((dLine = ffmpegOut.readLine()) != null) { logger.info(dLine); // fileOut.write(dLine); } // fileOut.close(); process.waitFor(); logger.info("***************************** end convert video *************************"); ffmpegOut.close(); return true; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } finally { try { if (null != ffmpegOut) { ffmpegOut.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static boolean checkfile(String path) { File file = new File(path); if (!file.isFile()) { return false; } return true; } // public static void main(String[] args) { // boolean bb = video2Flv("d:/ffmpeg/uploadVideo/Video1.wmv", // "d:/ffmpeg/convertedVideo/pp1.flv"); // logger.info("the bb result is " + bb); // boolean cc = video2Flv("d:/ffmpeg/uploadVideo/Video2.wmv", // "d:/ffmpeg/convertedVideo/pp2.flv"); // logger.info("the cc result is " + cc); // }[/code] 如上面的代码.上面的代码每次只能有一个视频在转换,如果想改进为最多同时有3个或者6个任务在执行呢? 此时是否要再设置一个信号量呢? [b]问题补充:[/b] [quote]放一个线程池(ThreadPool),可以解决你的问题,每次把你的任务丢到线程池里面。[/quote] 只知道连接数据库用到线程池.请求排队也可以用线程池?有这样的应用吗? 8) 并且具体如何用,能给个例子吗? [b]问题补充:[/b] [quote]jdk的cocurrent里面有现成的。 Java代码 queue = new LinkedBlockingQueue<Runnable>(1000); threadPool = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, queue); 这样就定义了一个线程池。 Java代码 threadPool.execute(runnable); 这样就放入线程池一个Runnable了,就可以满足你的需求了。[/quote] 感谢taopian的热心回复,马上看jdk的cocurrent. :) [b]问题补充:[/b] [quote]jdk的cocurrent里面有现成的。 [/quote] 谢谢了,cocurrent包,感觉很好,应该就是解决问题的办法了. :idea: 另外,我还有一个不好很明白,就是 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) 构造函数中的 BlockingQueue<Runnable> workQueue的作用? 感觉JVM可以在内部维护这个队列,不用释放出接口来. 当然尽管API上讲了" 大队列 用小池, 小队列 用大池," 可以提高资源利用率.然而现在还不是很理解.后面在实践中体会了. 嘿嘿 [b]问题补充:[/b] 先问再吃饭. :D [quote]BlockingQueue<Runnable> workQueue 这个就是放一个队列,任务扔到队列里面,可以对并发做控制。 把这个队列暴露出来,能够让你进行很好的控制,并且你可以继承BlockingQueue,来加入你自己需要的功能,:)。[/quote] 嗯,是的,可以自己继承BlockingQueue,再增加一些自己的功能,然后放入executor中去. 面向接口 :) 现在我已经可以顺利,并准确的运行了. 最后一个疑问: executor.excute(new Runnable(){ public void run(){ run 中的变量要求是final的.final变量的GC时间是否会有影响呢? 或者有别的更好解决方法 } } ) 我是这样的改的: 这个bean被迫为final的了.呵呵,有更好的方法吗? [code="java"]if (null != videoPath && null != flvPath) { final TaskBean task = new TaskBean(); task.setVideoPath(videoPath); task.setFlvPath(flvPath); threadPool.execute(new Runnable(){ public void run(){ MediaUtility.video2Flv(task.getVideoPath(), task.getFlvPath()); } });[/code] 哎呀,罗嗦了,吃饭先..... :D
condition.await()并发问题
public class BlockArrayList<E> extends ArrayList<E> { /** * long serialVersionUID:TODO(用一句话描述这个变量表示什么) * * @since 1.0.0 */ private static final long serialVersionUID = 1L; private ReentrantLock lock = new ReentrantLock(); private Condition notEmpty = lock.newCondition(); public int i = 0; public Exception ee; public E take() throws InterruptedException { try { lock.lock(); E e = null; int size = this.size(); if(size == 0) { notEmpty.await(); } i++; System.out.println(i); try { e = this.remove(0); } catch(Exception e1) { ee = e1; } return e; } finally { lock.unlock(); } } public boolean offer(E e) { try { lock.lock(); this.add(e); notEmpty.signal(); return true; } finally { lock.unlock(); } } public void op() { E s = null; try { s = this.take(); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() +" 被动结束"); e.printStackTrace(); } } public class MyThreadFactory implements ThreadFactory { private AtomicInteger NUMBER = new AtomicInteger(0); @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setName("shaoweiThread-"+NUMBER.decrementAndGet()); return t; } } public static void main(String[] args) { final BlockArrayList<String> list = new BlockArrayList<String>(); ThreadFactory threadThread = list.new MyThreadFactory(); Thread t = threadThread.newThread(new Runnable() { @Override public void run() { int i = 0; while(i <410000) { list.op(); } } }); t.start(); threadThread.newThread(new Runnable() { @Override public void run() { int i = 0; while(i <410000) { list.op(); } } }).start(); threadThread.newThread(new Runnable() { @Override public void run() { for(int i=0;i<400000;i++) { boolean flag = list.offer("item" + i); if(!flag) { System.out.println("添加元素失败"); } } System.out.println(list.ee); } }).start(); System.out.println("主线程结束"); } } 多个线程去取阻塞队列为啥会有并发问题呢?i正常应该为400000的,谁能给解释下
今天看JDK的一些原码,头都大了。。。
<pre name="code" class="java"> public interface Iterator&lt;E&gt; { boolean hasNext(); //是否有下一个元素 E next(); //下一个元素 void remove(); //删除 } public interface Collection&lt;E&gt; extends Iterable&lt;E&gt; { int size(); //包函的元素 boolean isEmpty(); //是否为空 boolean contains(Object o); //是否包括o Iterator&lt;E&gt; iterator(); //生成Iterator对象 Object[] toArray(); //生成数组对象 &lt;T&gt; T[] toArray(T[] a); // boolean add(E o); //加一个对象 boolean remove(Object o); //删除一个对象 boolean containsAll(Collection&lt;?&gt; c); // boolean addAll(Collection&lt;? extends E&gt; c); //添加所有的到当前集合,包括extends E的 boolean removeAll(Collection&lt;?&gt; c); // boolean retainAll(Collection&lt;?&gt; c); // void clear(); //清除 boolean equals(Object o); // int hashCode(); // } public interface List&lt;E&gt; extends Collection&lt;E&gt; { int size(); boolean isEmpty(); boolean contains(Object o); Iterator&lt;E&gt; iterator(); Object[] toArray(); &lt;T&gt; T[] toArray(T[] a); boolean add(E o); boolean remove(Object o); boolean containsAll(Collection&lt;?&gt; c); boolean addAll(Collection&lt;? extends E&gt; c); boolean addAll(int index, Collection&lt;? extends E&gt; c); boolean removeAll(Collection&lt;?&gt; c); boolean retainAll(Collection&lt;?&gt; c); void clear(); boolean equals(Object o); int hashCode(); //List接口里面自己的方法 E get(int index); //根据index值出相应的对象 E set(int index, E element); //设置相应位置的对象 void add(int index, E element); //增加相应位置的对象 E remove(int index); //删除 int indexOf(Object o); //根据对象获得相应对象的位置,没有找到应该会是-1 int lastIndexOf(Object o); //是最后一个开始找吧(不知道) ListIterator&lt;E&gt; listIterator(); //成生ListIterator对象,链表实现的吧 ListIterator&lt;E&gt; listIterator(int index); //成生ListIterator对象,从index开始生成 List&lt;E&gt; subList(int fromIndex, int toIndex); //从fromIndex到toIndex生成新的List对象 } public class ArrayList&lt;E&gt; extends AbstractList&lt;E&gt; implements List&lt;E&gt;, RandomAccess, Cloneable, java.io.Serializable{ private static final long serialVersionUID = 8683452581122892189L; //我不知道为什么会有一个这样的变量 private transient E[] elementData; //用来保存E的数组,ArrayList是数组实现的 private int size; //指这个数组保存的个数,并不是数组的大小 private int modCount; //构造方法 public ArrayList(int initialCapacity) { super(); if (initialCapacity &lt; 0){ throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity); } this.elementData = (E[])new Object[initialCapacity]; } public ArrayList() { this(10); } public ArrayList(Collection&lt;? extends E&gt; c) { size = c.size(); // Allow 10% room for growth int capacity = (int)Math.min((size*110L)/100, Integer.MAX_VALUE); elementData = (E[])c.toArray(new Object[capacity]); } /** * 看数组里面的元素和数组本身的长度,如果size&lt;length就可以缩小 * */ public void trimToSize() { modCount++; //这个到底是干什么用的? int oldCapacity = elementData.length; if (size &lt; oldCapacity) { Object oldData[] = elementData; elementData = (E[])new Object[size]; System.arraycopy(oldData, 0, elementData, 0, size); } } //扩大容量 public void ensureCapacity(int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity &gt; oldCapacity) { Object oldData[] = elementData; int newCapacity = (oldCapacity * 3)/2 + 1; //JDK1.5是这样写的哦,不知道为什么? if (newCapacity &lt; minCapacity){ newCapacity = minCapacity; //他的容量并一定扩大到minCapacity,满足条件才会扩大到那样 } elementData = (E[])new Object[newCapacity]; System.arraycopy(oldData, 0, elementData, 0, size); } } public int size() { return size; } public boolean isEmpty() { return size == 0; } //查个某个对象在数组中的位置,是否相于根据对象的equals方法 public int indexOf(Object elem) { if (elem == null) { for (int i = 0; i &lt; size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i &lt; size; i++) if (elem.equals(elementData[i])) return i; } return -1; } //这个方法和上面一个意思 public boolean contains(Object elem) { return indexOf(elem) &gt;= 0; } //很明显这个方法是从后向前找的 public int lastIndexOf(Object elem) { if (elem == null) { for (int i = size-1; i &gt;= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i &gt;= 0; i--) if (elem.equals(elementData[i])) return i; } return -1; } //克隆 //先复制这个对象,再复制这个对象中数组对象 public Object clone() { try { ArrayList&lt;E&gt; v = (ArrayList&lt;E&gt;) super.clone(); v.elementData = (E[])new Object[size]; System.arraycopy(elementData, 0, v.elementData, 0, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(); } } public Object[] toArray() { Object[] result = new Object[size]; System.arraycopy(elementData, 0, result, 0, size); return result; } //不知道什么意思。。。。 public &lt;T&gt; T[] toArray(T[] a) { if (a.length &lt; size){ a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size); } System.arraycopy(elementData, 0, a, 0, size); if (a.length &gt; size){ a[size] = null; } return a; } //获得 public E get(int index) { RangeCheck(index); //看是否超出size的大小 return elementData[index]; } //设置 public E set(int index, E element) { RangeCheck(index); E oldValue = elementData[index]; elementData[index] = element; return oldValue; } //增加一个对象 public boolean add(E o) { ensureCapacity(size + 1); // Increments modCount!! elementData[size++] = o; return true; } //在index这个位置后面加个对象进去 public void add(int index, E element) { if (index &gt; size || index &lt; 0){ throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size); } ensureCapacity(size+1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } public E remove(int index) { RangeCheck(index); modCount++; E oldValue = elementData[index]; int numMoved = size - index - 1; if (numMoved &gt; 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work return oldValue; } public boolean remove(Object o) { if (o == null) { for (int index = 0; index &lt; size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index &lt; size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } //private方法了 private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved &gt; 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work } public void clear() { modCount++; // Let gc do its work for (int i = 0; i &lt; size; i++){ elementData[i] = null; } size = 0; } public boolean addAll(Collection&lt;? extends E&gt; c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacity(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; } public boolean addAll(int index, Collection&lt;? extends E&gt; c) { if (index &gt; size || index &lt; 0) throw new IndexOutOfBoundsException( "Index: " + index + ", Size: " + size); Object[] a = c.toArray(); int numNew = a.length; ensureCapacity(size + numNew); // Increments modCount int numMoved = size - index; if (numMoved &gt; 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; } protected void removeRange(int fromIndex, int toIndex) { modCount++; int numMoved = size - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); // Let gc do its work int newSize = size - (toIndex-fromIndex); while (size != newSize){ elementData[--size] = null; } } private void RangeCheck(int index) { if (index &gt;= size){ throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size); } } private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException{ int expectedModCount = modCount; // Write out element count, and any hidden stuff s.defaultWriteObject(); // Write out array length s.writeInt(elementData.length); // Write out all elements in the proper order. for (int i=0; i&lt;size; i++){ s.writeObject(elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // Read in size, and any hidden stuff s.defaultReadObject(); // Read in array length and allocate array int arrayLength = s.readInt(); Object[] a = elementData = (E[])new Object[arrayLength]; // Read in all elements in the proper order. for (int i=0; i&lt;size; i++){ a[i] = s.readObject(); } } } public class Vector&lt;E&gt; extends AbstractList&lt;E&gt; implements List&lt;E&gt;, RandomAccess, Cloneable, java.io.Serializable{ protected Object[] elementData; protected int elementCount; protected int capacityIncrement; public Vector(int initialCapacity, int capacityIncrement) { super(); if (initialCapacity &lt; 0){ throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity); } this.elementData = new Object[initialCapacity]; this.capacityIncrement = capacityIncrement; } public Vector(int initialCapacity) { this(initialCapacity, 0); } public Vector() { this(10); } public Vector(Collection&lt;? extends E&gt; c) { elementCount = c.size(); // 10% for growth elementData = new Object[(int)Math.min((elementCount*110L)/100,Integer.MAX_VALUE)]; c.toArray(elementData); } //把这个Vector对象的数组复制到别一个去 public synchronized void copyInto(Object[] anArray) { System.arraycopy(elementData, 0, anArray, 0, elementCount); } public synchronized void trimToSize() { modCount++; int oldCapacity = elementData.length; if (elementCount &lt; oldCapacity) { Object oldData[] = elementData; elementData = new Object[elementCount]; System.arraycopy(oldData, 0, elementData, 0, elementCount); } } public synchronized void ensureCapacity(int minCapacity) { modCount++; ensureCapacityHelper(minCapacity); } private void ensureCapacityHelper(int minCapacity) { int oldCapacity = elementData.length; if (minCapacity &gt; oldCapacity) { Object[] oldData = elementData; int newCapacity = (capacityIncrement &gt; 0)?(oldCapacity+capacityIncrement):(oldCapacity*2); if (newCapacity &lt; minCapacity) { newCapacity = minCapacity; } elementData = new Object[newCapacity]; System.arraycopy(oldData, 0, elementData, 0, elementCount); } } public synchronized void setSize(int newSize) { modCount++; if (newSize &gt; elementCount) { ensureCapacityHelper(newSize); } else { for (int i = newSize ; i &lt; elementCount ; i++) { elementData[i] = null; } } elementCount = newSize; } public synchronized int capacity() { return elementData.length; } public synchronized int size() { return elementCount; } public synchronized boolean isEmpty() { return elementCount == 0; } public Enumeration&lt;E&gt; elements() { return new Enumeration&lt;E&gt;() { int count = 0; public boolean hasMoreElements() { return count &lt; elementCount; } public E nextElement() { synchronized (Vector.this) { if (count &lt; elementCount) { return (E)elementData[count++]; } } throw new NoSuchElementException("Vector Enumeration"); } }; } public boolean contains(Object elem) { return indexOf(elem, 0) &gt;= 0; } public int indexOf(Object elem) { return indexOf(elem, 0); } public synchronized int indexOf(Object elem, int index) { if (elem == null) { for (int i = index ; i &lt; elementCount ; i++) if (elementData[i]==null) return i; } else { for (int i = index ; i &lt; elementCount ; i++) if (elem.equals(elementData[i])) return i; } return -1; } public synchronized int lastIndexOf(Object elem) { return lastIndexOf(elem, elementCount-1); } public synchronized int lastIndexOf(Object elem, int index) { if (index &gt;= elementCount) throw new IndexOutOfBoundsException(index + " &gt;= "+ elementCount); if (elem == null) { for (int i = index; i &gt;= 0; i--) if (elementData[i]==null) return i; } else { for (int i = index; i &gt;= 0; i--) if (elem.equals(elementData[i])) return i; } return -1; } public synchronized E elementAt(int index) { if (index &gt;= elementCount) { throw new ArrayIndexOutOfBoundsException(index + " &gt;= " + elementCount); } return (E)elementData[index]; } //........................................ } public class Stack&lt;E&gt; extends Vector&lt;E&gt; { public Stack() { } public E push(E item) { addElement(item); //父类的方法 return item; } public synchronized E pop() { E obj; int len = size(); obj = peek(); removeElementAt(len - 1); return obj; } public synchronized E peek() { int len = size(); if (len == 0) throw new EmptyStackException(); return elementAt(len - 1); } public boolean empty() { return size() == 0; } public synchronized int search(Object o) { int i = lastIndexOf(o); if (i &gt;= 0) { return size() - i; } return -1; } } </pre><br /><strong>问题补充:</strong><br />写得不错呀,几个模式和线程同步都到的,有啥问题吗? <br />============================================= <br />这是JDK的源码,用到什么模式了啊,说一说啥<br /><strong>问题补充:</strong><br />哇,你太猛了,你知道怎么去看JDK的原代码么?那么多,没有方法是看不下去的哦。。。 <br /><br /><strong>问题补充:</strong><br />那你介绍几本书哦,我想把J2SE的基础搞的好一点。。 <br />我现在看的是Thanking Java 不过是讲的1.1版本的,看了两百多页就没有看下去了 <br />还在看的是数据结构(JAVA写的)........ <br />看了数据结构里面的链表才来看JDK里面的原码的,我以前就知道用,不知道里面是写的啥。。。
《奇巧淫技》系列-python!!每天早上八点自动发送天气预报邮件到QQ邮箱
将代码部署服务器,每日早上定时获取到天气数据,并发送到邮箱。 也可以说是一个小人工智障。 思路可以运用在不同地方,主要介绍的是思路。
Linux(服务器编程):15---两种高效的事件处理模式(reactor模式、proactor模式)
前言 同步I/O模型通常用于实现Reactor模式 异步I/O模型则用于实现Proactor模式 最后我们会使用同步I/O方式模拟出Proactor模式 一、Reactor模式 Reactor模式特点 它要求主线程(I/O处理单元)只负责监听文件描述符上是否有事件发生,有的话就立即将时间通知工作线程(逻辑单元)。除此之外,主线程不做任何其他实质性的工作 读写数据,接受新的连接,以及处...
为什么要学数据结构?
一、前言 在可视化化程序设计的今天,借助于集成开发环境可以很快地生成程序,程序设计不再是计算机专业人员的专利。很多人认为,只要掌握几种开发工具就可以成为编程高手,其实,这是一种误解。要想成为一个专业的开发人员,至少需要以下三个条件: 1) 能够熟练地选择和设计各种数据结构和算法 2) 至少要能够熟练地掌握一门程序设计语言 3) 熟知所涉及的相关应用领域的知识 其中,后两个条件比较容易实现,而第一个...
C语言魔塔游戏
很早就很想写这个,今天终于写完了。 游戏截图: 编译环境: VS2017 游戏需要一些图片,如果有想要的或者对游戏有什么看法的可以加我的QQ 2985486630 讨论,如果暂时没有回应,可以在博客下方留言,到时候我会看到。 下面我来介绍一下游戏的主要功能和实现方式 首先是玩家的定义,使用结构体,这个名字是可以自己改变的 struct gamerole { char n
进程通信方式总结与盘点
​ 进程通信是指进程之间的信息交换。这里需要和进程同步做一下区分,进程同步控制多个进程按一定顺序执行,进程通信是一种手段,而进程同步是目标。从某方面来讲,进程通信可以解决进程同步问题。 ​ 首先回顾下我们前面博文中讲到的信号量机制,为了实现进程的互斥与同步,需要在进程间交换一定的信息,因此信号量机制也可以被归为进程通信的一种方式,但是也被称为低级进程通信,主要原因为: 效率低:一次只可操作少量的...
究竟你适不适合买Mac?
我清晰的记得,刚买的macbook pro回到家,开机后第一件事情,就是上了淘宝网,花了500元钱,找了一个上门维修电脑的师傅,上门给我装了一个windows系统。。。。。。 表砍我。。。 当时买mac的初衷,只是想要个固态硬盘的笔记本,用来运行一些复杂的扑克软件。而看了当时所有的SSD笔记本后,最终决定,还是买个好(xiong)看(da)的。 已经有好几个朋友问我mba怎么样了,所以今天尽量客观
听说了吗?阿里双11作战室竟1根网线都没有
双11不光是购物狂欢节,更是对技术的一次“大考”,对于阿里巴巴企业内部运营的基础保障技术而言,亦是如此。 回溯双11历史,这背后也经历过“小米加步枪”的阶段:作战室从随处是网线,交换机放地上的“一地狼藉”;到如今媲美5G的wifi网速,到现场却看不到一根网线;从当年使用商用AP(无线路由器),让光明顶双11当天断网一分钟,到全部使用阿里自研AP……阿里巴巴企业智能事业部工程师们提供的基础保障...
在阿里,40岁的奋斗姿势
在阿里,40岁的奋斗姿势 在阿里,什么样的年纪可以称为老呢?35岁? 在云网络,有这样一群人,他们的平均年龄接近40,却刚刚开辟职业生涯的第二战场。 他们的奋斗姿势是什么样的呢? 洛神赋 “翩若惊鸿,婉若游龙。荣曜秋菊,华茂春松。髣髴兮若轻云之蔽月,飘飖兮若流风之回雪。远而望之,皎若太阳升朝霞;迫而察之,灼若芙蕖出渌波。” 爱洛神,爱阿里云 2018年,阿里云网络产品部门启动洛神2.0升...
关于研发效能提升的思考
研发效能提升是最近比较热门的一个话题,本人根据这几年的工作心得,做了一些思考总结,由于个人深度有限,暂且抛转引入。 三要素 任何生产力的提升都离不开这三个因素:人、流程和工具,少了其中任何一个因素都无法实现。 人,即思想,也就是古人说的“道”,道不同不相为谋,是制高点,也是高层建筑的基石。 流程,即方法,也是古人说的“法”。研发效能的提升,也就是要提高投入产出比,既要增加产出,也要减...
Python爬虫爬取淘宝,京东商品信息
小编是一个理科生,不善长说一些废话。简单介绍下原理然后直接上代码。 使用的工具(Python+pycharm2019.3+selenium+xpath+chromedriver)其中要使用pycharm也可以私聊我selenium是一个框架可以通过pip下载 pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple/ 
阿里程序员写了一个新手都写不出的低级bug,被骂惨了。
这种新手都不会范的错,居然被一个工作好几年的小伙子写出来,差点被当场开除了。
Java工作4年来应聘要16K最后没要,细节如下。。。
前奏: 今天2B哥和大家分享一位前几天面试的一位应聘者,工作4年26岁,统招本科。 以下就是他的简历和面试情况。 基本情况: 专业技能: 1、&nbsp;熟悉Sping了解SpringMVC、SpringBoot、Mybatis等框架、了解SpringCloud微服务 2、&nbsp;熟悉常用项目管理工具:SVN、GIT、MAVEN、Jenkins 3、&nbsp;熟悉Nginx、tomca
2020年,冯唐49岁:我给20、30岁IT职场年轻人的建议
点击“技术领导力”关注∆  每天早上8:30推送 作者| Mr.K   编辑| Emma 来源| 技术领导力(ID:jishulingdaoli) 前天的推文《冯唐:职场人35岁以后,方法论比经验重要》,收到了不少读者的反馈,觉得挺受启发。其实,冯唐写了不少关于职场方面的文章,都挺不错的。可惜大家只记住了“春风十里不如你”、“如何避免成为油腻腻的中年人”等不那么正经的文章。 本文整理了冯
程序员该看的几部电影
##1、骇客帝国(1999) 概念:在线/离线,递归,循环,矩阵等 剧情简介: 不久的将来,网络黑客尼奥对这个看似正常的现实世界产生了怀疑。 他结识了黑客崔妮蒂,并见到了黑客组织的首领墨菲斯。 墨菲斯告诉他,现实世界其实是由一个名叫“母体”的计算机人工智能系统控制,人们就像他们饲养的动物,没有自由和思想,而尼奥就是能够拯救人类的救世主。 可是,救赎之路从来都不会一帆风顺,到底哪里才是真实的世界?
入职阿里5年,他如何破解“技术债”?
简介: 作者 | 都铎 作为一名技术人,你常常会听到这样的话: “先快速上线” “没时间改” “再缓一缓吧” “以后再解决” “先用临时方案处理” …… 当你埋下的坑越来越多,不知道哪天哪位同学就会踩上一颗雷。特别赞同“人最大的恐惧就是未知,当技术债可说不可见的时候,才是最让人不想解决的时候。” 作为一个程序员,我们反对复制粘贴,但是我们经常会见到相似的代码,相同的二方包,甚至整个代码...
Python绘图,圣诞树,花,爱心 | Turtle篇
每周每日,分享Python实战代码,入门资料,进阶资料,基础语法,爬虫,数据分析,web网站,机器学习,深度学习等等。 公众号回复【进群】沟通交流吧,QQ扫码进群学习吧 微信群 QQ群 1.画圣诞树 import turtle screen = turtle.Screen() screen.setup(800,600) circle = turtle.Turtle()...
作为一个程序员,CPU的这些硬核知识你必须会!
CPU对每个程序员来说,是个既熟悉又陌生的东西? 如果你只知道CPU是中央处理器的话,那可能对你并没有什么用,那么作为程序员的我们,必须要搞懂的就是CPU这家伙是如何运行的,尤其要搞懂它里面的寄存器是怎么一回事,因为这将让你从底层明白程序的运行机制。 随我一起,来好好认识下CPU这货吧 把CPU掰开来看 对于CPU来说,我们首先就要搞明白它是怎么回事,也就是它的内部构造,当然,CPU那么牛的一个东
破14亿,Python分析我国存在哪些人口危机!
2020年1月17日,国家统计局发布了2019年国民经济报告,报告中指出我国人口突破14亿。 猪哥的朋友圈被14亿人口刷屏,但是很多人并没有看到我国复杂的人口问题:老龄化、男女比例失衡、生育率下降、人口红利下降等。 今天我们就来分析一下我们国家的人口数据吧! 一、背景 1.人口突破14亿 2020年1月17日,国家统计局发布了 2019年国民经济报告 ,报告中指出:年末中国大陆总人口(包括31个
在家远程办公效率低?那你一定要收好这个「在家办公」神器!
相信大家都已经收到国务院延长春节假期的消息,接下来,在家远程办公可能将会持续一段时间。 但是问题来了。远程办公不是人在电脑前就当坐班了,相反,对于沟通效率,文件协作,以及信息安全都有着极高的要求。有着非常多的挑战,比如: 1在异地互相不见面的会议上,如何提高沟通效率? 2文件之间的来往反馈如何做到及时性?如何保证信息安全? 3如何规划安排每天工作,以及如何进行成果验收? ......
作为一个程序员,内存和磁盘的这些事情,你不得不知道啊!!!
截止目前,我已经分享了如下几篇文章: 一个程序在计算机中是如何运行的?超级干货!!! 作为一个程序员,CPU的这些硬核知识你必须会! 作为一个程序员,内存的这些硬核知识你必须懂! 这些知识可以说是我们之前都不太重视的基础知识,可能大家在上大学的时候都学习过了,但是嘞,当时由于老师讲解的没那么有趣,又加上这些知识本身就比较枯燥,所以嘞,大家当初几乎等于没学。 再说啦,学习这些,也看不出来有什么用啊!
2020年的1月,我辞掉了我的第一份工作
其实,这篇文章,我应该早点写的,毕竟现在已经2月份了。不过一些其它原因,或者是我的惰性、还有一些迷茫的念头,让自己迟迟没有试着写一点东西,记录下,或者说是总结下自己前3年的工作上的经历、学习的过程。 我自己知道的,在写自己的博客方面,我的文笔很一般,非技术类的文章不想去写;另外我又是一个还比较热衷于技术的人,而平常复杂一点的东西,如果想写文章写的清楚点,是需要足够...
别低估自己的直觉,也别高估自己的智商
所有群全部吵翻天,朋友圈全部沦陷,公众号疯狂转发。这两周没怎么发原创,只发新闻,可能有人注意到了。我不是懒,是文章写了却没发,因为大家的关注力始终在这次的疫情上面,发了也没人看。当然,我...
Java坑人面试题系列: 包装类(中级难度)
Java Magazine上面有一个专门坑人的面试题系列: https://blogs.oracle.com/javamagazine/quiz-2。 这些问题的设计宗旨,主要是测试面试者对Java语言的了解程度,而不是为了用弯弯绕绕的手段把面试者搞蒙。 如果你看过往期的问题,就会发现每一个都不简单。 这些试题模拟了认证考试中的一些难题。 而 “中级(intermediate)” 和 “高级(ad
深度学习入门笔记(十八):卷积神经网络(一)
欢迎关注WX公众号:【程序员管小亮】 专栏——深度学习入门笔记 声明 1)该文章整理自网上的大牛和机器学习专家无私奉献的资料,具体引用的资料请看参考文献。 2)本文仅供学术交流,非商用。所以每一部分具体的参考资料并没有详细对应。如果某部分不小心侵犯了大家的利益,还望海涵,并联系博主删除。 3)博主才疏学浅,文中如有不当之处,请各位指出,共同进步,谢谢。 4)此属于第一版本,若有错误,还需继续修正与...
这个世界上人真的分三六九等,你信吗?
偶然间,在知乎上看到一个问题 一时间,勾起了我深深的回忆。 以前在厂里打过两次工,做过家教,干过辅导班,做过中介。零下几度的晚上,贴过广告,满脸、满手地长冻疮。 再回首那段岁月,虽然苦,但让我学会了坚持和忍耐。让我明白了,在这个世界上,无论环境多么的恶劣,只要心存希望,星星之火,亦可燎原。 下文是原回答,希望能对你能有所启发。 如果我说,这个世界上人真的分三六九等,...
节后首个工作日,企业们集体开晨会让钉钉挂了
By 超神经场景描述:昨天 2 月 3 日,是大部分城市号召远程工作的第一天,全国有接近 2 亿人在家开始远程办公,钉钉上也有超过 1000 万家企业活跃起来。关键词:十一出行 人脸...
Java基础知识点梳理
Java基础知识点梳理 摘要: 虽然已经在实际工作中经常与java打交道,但是一直没系统地对java这门语言进行梳理和总结,掌握的知识也比较零散。恰好利用这段时间重新认识下java,并对一些常见的语法和知识点做个总结与回顾,一方面为了加深印象,方便后面查阅,一方面为了学好java打下基础。 Java简介 java语言于1995年正式推出,最开始被命名为Oak语言,由James Gosling(詹姆
2020年全新Java学习路线图,含配套视频,学完即为中级Java程序员!!
新的一年来临,突如其来的疫情打破了平静的生活! 在家的你是否很无聊,如果无聊就来学习吧! 世上只有一种投资只赚不赔,那就是学习!!! 传智播客于2020年升级了Java学习线路图,硬核升级,免费放送! 学完你就是中级程序员,能更快一步找到工作! 一、Java基础 JavaSE基础是Java中级程序员的起点,是帮助你从小白到懂得编程的必经之路。 在Java基础板块中有6个子模块的学
B 站上有哪些很好的学习资源?
哇说起B站,在小九眼里就是宝藏般的存在,放年假宅在家时一天刷6、7个小时不在话下,更别提今年的跨年晚会,我简直是跪着看完的!! 最早大家聚在在B站是为了追番,再后来我在上面刷欧美新歌和漂亮小姐姐的舞蹈视频,最近两年我和周围的朋友们已经把B站当作学习教室了,而且学习成本还免费,真是个励志的好平台ヽ(.◕ฺˇд ˇ◕ฺ;)ノ 下面我们就来盘点一下B站上优质的学习资源: 综合类 Oeasy: 综合
你也能看懂的:蒙特卡罗方法
蒙特卡罗方法,也称统计模拟方法,是1940年代中期由于科学技术的发展和电子计算机的发明,而提出的一种以概率统计理论为指导的数值计算方法。是指使用随机数(或更常见的伪随机数)来解决很多计算问题的方法 蒙特卡罗方法可以粗略地分成两类:一类是所求解的问题本身具有内在的随机性,借助计算机的运算能力可以直接模拟这种随机的过程。另一种类型是所求解问题可以转化为某种随机分布的特征数,比如随机事件出现的概率,或...
如何优雅地打印一个Java对象?
你好呀,我是沉默王二,一个和黄家驹一样身高,和刘德华一样颜值的程序员。虽然已经写了十多年的 Java 代码,但仍然觉得自己是个菜鸟(请允许我惭愧一下)。 在一个月黑风高的夜晚,我思前想后,觉得再也不能这么蹉跎下去了。于是痛下决心,准备通过输出的方式倒逼输入,以此来修炼自己的内功,从而进阶成为一名真正意义上的大神。与此同时,希望这些文章能够帮助到更多的读者,让大家在学习的路上不再寂寞、空虚和冷。 ...
雷火神山直播超两亿,Web播放器事件监听是怎么实现的?
Web播放器解决了在手机浏览器和PC浏览器上播放音视频数据的问题,让视音频内容可以不依赖用户安装App,就能进行播放以及在社交平台进行传播。在视频业务大数据平台中,播放数据的统计分析非常重要,所以Web播放器在使用过程中,需要对其内部的数据进行收集并上报至服务端,此时,就需要对发生在其内部的一些播放行为进行事件监听。 那么Web播放器事件监听是怎么实现的呢? 01 监听事件明细表 名...
JAVA后端面试《Spring》
Spring1.Spring是什么?有什么好处?2.IOC是什么?有什么好处?具体过程?3.DI是什么?4.IOC和DI的关系?5.bean标签的属性有哪些?6.IOC创建对象有哪几种方式?7.Spring是如何实现IOC的?也就是如何创建对象的? 1.Spring是什么?有什么好处? 概念: SPring是一个支持控制反转(IOC)和面向切面编程(AOP)的容器框架。 好处: 两降低&gt;&...
AI 医生“战疫”在前线
作者| Just出品|CSDN(CSDNnews)紧急驰援疫区,AI医生也出动了。截止到2月6日,随着新冠病毒肺炎疫情的不断发展,全国累计已有31161例确诊病例,26359例疑...
相关热词 c# 识别回车 c#生成条形码ean13 c#子控制器调用父控制器 c# 写大文件 c# 浏览pdf c#获取桌面图标的句柄 c# list反射 c# 句柄 进程 c# 倒计时 线程 c# 窗体背景色
立即提问