public class Cycle {
private final int result;
private static final Cycle self = new Cycle();
private static final int randomNumber = (int)(Math.random()*100);
public Cycle(){
System.out.println("randomNumber:"+randomNumber);
result = randomNumber - 10;
}
public static void main(String args[]){
System.out.println(self.result);
}
}
上面这段代码会永远输出 -10 , 而不是随机值
再仔细看看这句话
当你使用一个类的静态成员变量时,会触发这个类的构造器函数
也就是说当代码执行到第四行
private static final Cycle self = new Cycle();
此时出现了第一个静态变量self, 接着jvm就需要调用构造器了
public Cycle(){
System.out.println("randomNumber:"+randomNumber);
result = randomNumber - 10;
}
注意此时randomNumber的值还是0 , 因为它还没有被赋值
正确的做法是在类调用构造器之前初始化randomNumber
public class CycleCorrected {
private static final int randomNumber = (int)(Math.random()*100);
private final int result;
private static final CycleCorrected self = new CycleCorrected();
public CycleCorrected(){
System.out.println("randomNumber:"+randomNumber);
result = randomNumber - 10;
}
public static void main(String args[]){
System.out.println(self.result);
}
}
其实上面的代码稍作改动, 还可以观察到一个Exception in thread “main” java.lang.StackOverflowError
public class App {
private final int result;
private final App self = new App();
private static final int randomNumber = (int)(Math.random()*100);
public App(){
System.out.println("randomNumber:"+randomNumber);
result = randomNumber - 10;
}
public static void main(String args[]){
System.out.println(new App().result);
}
}
import java.util.Arrays;
public class Test {
public static void main(String args[]){
int[] a = new int[10];
int[] b = new int[10];
System.out.println(a[0]);
System.out.println(a==b);
System.out.println(Arrays.equals(a, b));
}
}
package name.lizhe.exe;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Executor {
public static void main(String args[]){
new ClassPathXmlApplicationContext("applicationContext.xml");
}
}
$CATALINA_HOME/bin/bootstrap.jar — Contains the main() method that is used to initialize the Tomcat server, and the class loader implementation classes it depends on.
$CATALINA_BASE/bin/tomcat-juli.jar or $CATALINA_HOME/bin/tomcat-juli.jar — Logging implementation classes. These include enhancement classes to java.util.logging API, known as Tomcat JULI, and a package-renamed copy of Apache Commons Logging library used internally by Tomcat. See logging documentation for more details.
If tomcat-juli.jar is present in $CATALINA_BASE/bin, it is used instead of the one in $CATALINA_HOME/bin. It is useful in certain logging configurations
$CATALINA_HOME/bin/commons-daemon.jar — The classes from Apache Commons Daemon project. This JAR file is not present in the CLASSPATH built by catalina.bat|.sh scripts, but is referenced from the manifest file of bootstrap.jar.
Common classloader 用于加载tomcat lib目录下的jar和class, 不要把webapp相关jar放在这里
unpacked classes and resources in $CATALINA_BASE/lib
JAR files in $CATALINA_BASE/lib
unpacked classes and resources in $CATALINA_HOME/lib
JAR files in $CATALINA_HOME/lib
annotations-api.jar — JavaEE annotations classes.
catalina.jar — Implementation of the Catalina servlet container portion of Tomcat.
catalina-ant.jar — Tomcat Catalina Ant tasks.
catalina-ha.jar — High availability package.
catalina-tribes.jar — Group communication package.
ecj-*.jar — Eclipse JDT Java compiler.
el-api.jar — EL 2.2 API.
jasper.jar — Tomcat Jasper JSP Compiler and Runtime.
jasper-el.jar — Tomcat Jasper EL implementation.
jsp-api.jar — JSP 2.2 API.
servlet-api.jar — Servlet 3.0 API.
tomcat-api.jar — Several interfaces defined by Tomcat.
tomcat-coyote.jar — Tomcat connectors and utility classes.
tomcat-dbcp.jar — Database connection pool implementation based on package-renamed copy of Apache Commons Pool and Apache Commons DBCP.
tomcat-i18n-**.jar — Optional JARs containing resource bundles for other languages. As default bundles are also included in each individual JAR, they can be safely removed if no internationalization of messages is needed.
tomcat-jdbc.jar — An alternative database connection pool implementation, known as Tomcat JDBC pool. See documentation for more details.
tomcat-util.jar — Common classes used by various components of Apache Tomcat.
WebappX — A class loader is created for each web application that is deployed in a single Tomcat instance. All unpacked classes and resources in the /WEB-INF/classes directory of your web application, plus classes and resources in JAR files under the /WEB-INF/lib directory of your web application, are made visible to this web application, but not to other ones.
package myanno;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class Test {
@MyAutoValue("hello world")
public static String value;
public static void main(String args[]) throws ClassNotFoundException, NoSuchFieldException, SecurityException{
Class clazz = Class.forName("myanno.Test");
Field field = clazz.getField("value");
Annotation[] ans = field.getAnnotations();
System.out.println(((MyAutoValue) ans[0]).value());
}
}
public class Test {
public static void main(String args[]) throws InterruptedException{
Thread t = new Thread(new Runnable(){
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
System.out.println("running...");
}
}
});
t.start();
Thread.sleep(1000);
t.interrupt();
}
}
方案2: 使用volatile关键字的表示位
public class Test {
volatile static boolean stop = false;
public static void main(String args[]) throws InterruptedException{
Thread t = new Thread(new Runnable(){
@Override
public void run() {
while(!stop){
System.out.println("running...");
}
}
});
t.start();
Thread.sleep(1000);
stop=true;
}
}
方案3: 使用中断让线程抛出InterruptedException
public class Test {
public static void main(String args[]) throws Exception{
Thread t = new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.currentThread().sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
System.out.println("running...");
}
}
});
t.start();
Thread.sleep(1000);
t.interrupt();
}
}
package com.lz.exe;
import java.util.List;
import java.util.Stack;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.stream.Collectors;
import com.lz.bean.Flag;
import com.lz.bean.Student;
import com.lz.tool.DataFactory;
import com.lz.tool.Worker;
public class Executor {
volatile static boolean done = false; //错误的方式
public static void main(String args[]) {
// List<Student> data = DataFactory.getRandomDummyData(10000000);
Stack<Student> data = DataFactory.getDummyData(20);
ExecutorService executor = Executors.newFixedThreadPool(2);
Flag flag = new Flag();
String result = "NONE";
/** 错误的方式
Future<String> f1 = executor.submit(new Worker(data, done));
Future<String> f2 = executor.submit(new Worker(data, done));
Future<String> f3 = executor.submit(new Worker(data, done));
Future<String> f4 = executor.submit(new Worker(data, done));
**/
Future<String> f1 = executor.submit(new Worker(data, flag));
Future<String> f2 = executor.submit(new Worker(data, flag));
Future<String> f3 = executor.submit(new Worker(data, flag));
Future<String> f4 = executor.submit(new Worker(data, flag));
Long start = System.currentTimeMillis();
System.out.println("started");
try {
if (f1.get() != "") {
result = f1.get();
System.out.println(1);
}
if (f2.get() != "") {
result = f2.get();
System.out.println(2);
}
if (f3.get() != "") {
result = f3.get();
System.out.println(3);
}
if (f4.get() != "") {
result = f4.get();
System.out.println(4);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executor.shutdownNow();
}
Long end = System.currentTimeMillis();
executor.shutdown();
System.out.println(result);
System.out.println(end - start);
}
}
package com.lz.tool;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.lz.bean.Student;
public class DataFactory {
public static List<Student> getRandomDummyData(int count){
List<Integer> list = Stream.generate(Math::random).distinct().filter(i -> i < 1).limit(count).map(i -> i * 100000)
.map(Double::intValue).collect(Collectors.toList());
List<Student> students = new ArrayList<Student>();
for(Integer i:list){
Student stu = new Student("name"+i,i);
students.add(stu);
}
return students;
}
public static Stack<Student> getDummyData(int count){
Stack<Student> students = new Stack<Student>();
for(int i=0;i<count;i++){
Student stu = new Student("name"+i,i);
students.add(stu);
}
return students;
}
}
package com.lz.tool;
import java.util.Stack;
import java.util.concurrent.Callable;
import com.lz.bean.Flag;
import com.lz.bean.Student;
public class Worker implements Callable<String>{
private Stack<Student> students;
volatile private boolean done= false; //错误的方式
private Flag flag;
public Worker(Stack<Student> students, boolean done) {
this.students = students;
this.done = done;
}
public Worker(Stack<Student> students, Flag flag) {
this.students = students;
this.flag = flag;
}
@Override
public String call() throws Exception {
String result = "";
while(!flag.done){
if(!students.isEmpty()){
Student stu = students.pop();
System.out.println("doing "+stu.getAge()+" "+Thread.currentThread() + " " + flag.done);
if(stu.getAge()==10){
result = stu.getName();
flag.done = true;
break;
}
}
}
return result;
}
}
package com.lz.bean;
public class Student {
private String name = "";
private int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
// System.out.println("call get age for"+age+" "+Thread.currentThread());
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.lz.bean;
public class Flag {
public volatile boolean done = false;
}
package com.lz.bean;
public class Student {
private String name = "";
private int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
// System.out.println("call get age for"+age+" "+Thread.currentThread());
return age;
}
public void setAge(int age) {
this.age = age;
}
}
用来做dummy数据的测试类
package com.lz.tool;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.lz.bean.Student;
public class DataFactory {
public static List<Student> getRandomDummyData(int count){
List<Integer> list = Stream.generate(Math::random).distinct().filter(i -> i < 1).limit(count).map(i -> i * 100000)
.map(Double::intValue).collect(Collectors.toList());
List<Student> students = new ArrayList<Student>();
for(Integer i:list){
Student stu = new Student("name"+i,i);
students.add(stu);
}
return students;
}
public static List<Student> getDummyData(int count){
List<Student> students = new ArrayList<Student>();
for(int i=0;i<count;i++){
Student stu = new Student("name"+i,i);
students.add(stu);
}
return students;
}
}
线程类
package com.lz.tool;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import com.lz.bean.Student;
public class Worker implements Callable<String>{
private List<Student> students;
private ExecutorService executor;
public Worker(List<Student> students, ExecutorService executor) {
this.students = students;
this.executor = executor;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public ExecutorService getExecutor() {
return executor;
}
public void setExecutor(ExecutorService executor) {
this.executor = executor;
}
@Override
public String call() throws Exception {
String result = "";
for(Student stu:students){
if(stu.getAge()==7300000){
result = stu.getName();
break;
}
}
if(result!=""){
System.out.println(Thread.currentThread()+" i shutdown the pool");
executor.shutdownNow();
}
System.out.println(Thread.currentThread()+"/"+result);
return result;
}
}
主启动类
package com.lz.exe;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.stream.Collectors;
import com.lz.bean.Student;
import com.lz.tool.DataFactory;
import com.lz.tool.Worker;
public class Executor {
public static void main(String args[]) {
// List<Student> data = DataFactory.getRandomDummyData(10000000);
List<Student> data = DataFactory.getDummyData(10000000);
ExecutorService executor = Executors.newFixedThreadPool(2);
String result = "NONE";
Future<String> f1 = executor.submit(new Worker(data.subList(0, data.size() / 4 * 1), executor));
Future<String> f2 = executor
.submit(new Worker(data.subList(data.size() / 4 * 1, data.size() / 4 * 2), executor));
Future<String> f3 = executor
.submit(new Worker(data.subList(data.size() / 4 * 2, data.size() / 4 * 3), executor));
Future<String> f4 = executor
.submit(new Worker(data.subList(data.size() / 4 * 3, data.size() / 4 * 4), executor));
Long start = System.currentTimeMillis();
System.out.println("started");
try {
if (f1.get() != "") {
result = f1.get();
System.out.println(1);
}
if (f2.get() != "") {
result = f2.get();
System.out.println(2);
}
if (f3.get() != "") {
result = f3.get();
System.out.println(3);
}
if (f4.get() != "") {
result = f4.get();
System.out.println(4);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executor.shutdownNow();
}
Long end = System.currentTimeMillis();
executor.shutdown();
System.out.println(result);
System.out.println(end - start);
}
}
这里的问题是
当线程池设置为4或者2时, 程序正常运行并且结束
当线程池设置为1时, 程序无法正常退出
f3执行完成之后, f4.get() 会永久阻塞
started
Thread[pool-1-thread-1,5,main]/
Thread[pool-1-thread-1,5,main]/
Thread[pool-1-thread-1,5,main] i shutdown the pool
Thread[pool-1-thread-1,5,main]/name7300000
3
package testatomic;
public class Data {
public volatile long value1;
public volatile long value2;
public volatile long value3;
public volatile long value4;
}
package testatomic;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class TestAtomic3 extends Thread{
public static void main(String args[]) throws InterruptedException{
Data data = new Data();
ExecutorService es = Executors.newFixedThreadPool(4);
long start = System.currentTimeMillis();
int loopcont = 1000000000;
Thread t[] = new Thread[4];
t[0] = new Thread( () -> {
for(int i=0;i<loopcont;i++){
data.value1 = data.value1+i;
}
} );
t[1] = new Thread( () -> {
for(int i=0;i<loopcont;i++){
data.value2 = data.value2+i;
}
} );
t[2] = new Thread( () -> {
for(int i=0;i<loopcont;i++){
data.value3 = data.value3+i;
}
} );
t[3] = new Thread( () -> {
for(int i=0;i<loopcont;i++){
data.value4 = data.value4+i;
}
} );
for(Thread item:t){
es.submit(item);
}
for(Thread item:t){
item.join();
}
es.shutdown();
es.awaitTermination(9999999, TimeUnit.SECONDS);
long end = System.currentTimeMillis();
System.out.println(end-start);
}
}