publicenumState{/** * Thread state for a thread which has not yet started. */NEW,/** * Thread state for a runnable thread. A thread in the runnable * state is executing in the Java virtual machine but it may * be waiting for other resources from the operating system * such as processor. */RUNNABLE,/** * Thread state for a thread blocked waiting for a monitor lock. * A thread in the blocked state is waiting for a monitor lock * to enter a synchronized block/method or * reenter a synchronized block/method after calling * {@link Object#wait() Object.wait}. */BLOCKED,/** * Thread state for a waiting thread. * A thread is in the waiting state due to calling one of the * following methods: * <ul> * <li>{@link Object#wait() Object.wait} with no timeout</li> * <li>{@link #join() Thread.join} with no timeout</li> * <li>{@link LockSupport#park() LockSupport.park}</li> * </ul> * * <p>A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called <tt>Object.wait()</tt> * on an object is waiting for another thread to call * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on * that object. A thread that has called <tt>Thread.join()</tt> * is waiting for a specified thread to terminate. */WAITING,/** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: * <ul> * <li>{@link #sleep Thread.sleep}</li> * <li>{@link Object#wait(long) Object.wait} with timeout</li> * <li>{@link #join(long) Thread.join} with timeout</li> * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> * </ul> */TIMED_WAITING,/** * Thread state for a terminated thread. * The thread has completed execution. */TERMINATED;}
packageexample.juc.test2;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;publicclassTestLock{publicstaticvoidmain(String[] args){TicketTask ticketTask =newTicketTask();newThread(()->{for(int i =0; i <1000; i++){ ticketTask.ticket();}},"线程A").start();newThread(()->{for(int i =0; i <1000; i++){ ticketTask.ticket();}},"线程B").start();newThread(()->{for(int i =0; i <1000; i++){ ticketTask.ticket();}},"线程C").start();}}classTicketTask{privateint number =30;privateLock lock =newReentrantLock();publicvoidticket(){ lock.lock();try{if(number >0){try{Thread.sleep(10);}catch(InterruptedException e){thrownewRuntimeException(e);} number--;System.out.println(Thread.currentThread().getName()+"完成售票:"+ number);}}finally{ lock.unlock();}}}
packageexample.juc2.test;importjava.util.concurrent.TimeUnit;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;publicclassTestTryLock{privatestaticfinalLock lock =newReentrantLock();privatestaticint sum =0;publicstaticvoidmain(String[] args){for(int i =0; i <1000; i++){newThread(()->{if(lock.tryLock()){try{ sum ++;System.out.println(Thread.currentThread().getName()+" - "+ sum);}catch(Exception e){thrownewRuntimeException(e);}finally{ lock.unlock();}}}).start();}}}
packageexample.juc2.test;importjava.util.concurrent.TimeUnit;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;publicclassTestTryLock{privatestaticfinalLock lock =newReentrantLock();privatestaticint sum =0;publicstaticvoidmain(String[] args){for(int i =0; i <1000; i++){newThread(()->{try{if(lock.tryLock(5,TimeUnit.SECONDS)){try{ sum ++;System.out.println(Thread.currentThread().getName()+" - "+ sum);TimeUnit.SECONDS.sleep(1);}catch(Exception e){thrownewRuntimeException(e);}finally{ lock.unlock();}}}catch(InterruptedException e){thrownewRuntimeException(e);}}).start();}}}
packageexample.juc2.test;importjava.util.concurrent.locks.Condition;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;publicclassTestThreadOrderAccess{publicstaticclassShareResource{privatechar flag ='A';privatefinalLock lock =newReentrantLock();privatefinalCondition conditionA = lock.newCondition();privatefinalCondition conditionB = lock.newCondition();privatefinalCondition conditionC = lock.newCondition();publicvoiddoA(){ lock.lock();try{while(flag !='A'){ conditionA.await();}for(int i =0; i <5; i++){System.out.println(Thread.currentThread().getName()+"\t"+i);} flag ='B'; conditionB.signal();}catch(InterruptedException e){thrownewRuntimeException(e);}finally{ lock.unlock();}}publicvoiddoB(){ lock.lock();try{while(flag !='B'){ conditionB.await();}for(int i =0; i <10; i++){System.out.println(Thread.currentThread().getName()+"\t"+i);} flag ='C'; conditionC.signal();}catch(InterruptedException e){thrownewRuntimeException(e);}finally{ lock.unlock();}}publicvoiddoC(){ lock.lock();try{while(flag !='C'){ conditionC.await();}for(int i =0; i <15; i++){System.out.println(Thread.currentThread().getName()+"\t"+i);}System.out.println("*********"); flag ='A'; conditionA.signal();}catch(InterruptedException e){thrownewRuntimeException(e);}finally{ lock.unlock();}}}publicstaticvoidmain(String[] args){ShareResource shareResource =newShareResource();newThread(()->{for(int i =0; i <3; i++){ shareResource.doA();}},"A").start();newThread(()->{for(int i =0; i <3; i++){ shareResource.doB();}},"B").start();newThread(()->{for(int i =0; i <3; i++){ shareResource.doC();}},"C").start();}}
publicclassDemo{//编译出错❌ 'test(List<String>)' clashes with 'test(List<Integer>)'; both methods have same erasurevoidtest(List<String> list){}voidtest(List<Integer> list){}}
再来看super,super和extends的情况会略有不同,super代表限制类型为某种类型及父类,设置的是类型的下限,保证传入的泛型类型不能低于某个类型,super修饰的泛型可读,但只能读出为Object,可写,但只能写入对应类型及其子类,例如? super Cat修饰的变量只允许赋值Cat类及其子类的对象,因为Cat类及其子类的对象肯定可以被Cat类及其父类的引用指向
举例来讲的话,可以传给List<? super Cat> list的不是“List<猫>”就是“List<动物>”,所以首先不能add“动物”进去,因为有可能传进来的是“List<猫>”,只有“动物”包含“猫”,没有“猫”包含“动物”。同理,不能add“狗”进去,因为“狗”属于“动物”但不属于“猫”(废话)。所以只有“猫”和“英短”以及“布偶”能add进去,因为无论传进来的是“List<猫>”还是“List<动物>”,“英短”和“布偶”既直接继承自“猫”,也间接继承自“动物”,而“猫”本身就能添加进去
@FunctionalInterfaceinterfaceConvert{Integerfun(String s);}@Testpublicvoidtest8(){Convert convert = from ->Integer.valueOf(from);System.out.println(convert.fun("150")+1);}@Testpublicvoidtest9(){Convert convert =Integer::valueOf;System.out.println(convert.fun("150")+1);}
例: 特定对象::实例方法
@FunctionalInterfaceinterfaceConvert{Integerfun(String s);}@Testpublicvoidtest8(){Convert convert = from ->"liuzijian.com".indexOf(from);System.out.println(convert.fun("zi"));}@Testpublicvoidtest9(){Convert convert ="liuzijian.com"::indexOf;System.out.println(convert.fun("zi"));}
例: 类名::实例方法
@FunctionalInterfaceinterfaceFun{Stringtest(String a,int b,int c);}@Testpublicvoidtest8(){Fun fun =(a, b, c)-> a.substring(b, c);String s = fun.test("abcdefghi",3,5);System.out.println(s);}@Testpublicvoidtest9(){Fun fun =String::substring;String s = fun.test("abcdefghi",3,5);System.out.println(s);}
例: 类名::new
@FunctionalInterfaceinterfaceFun{BigDecimaltest(String n);}@Testpublicvoidtest8(){Fun fun =(n)->newBigDecimal(n);BigDecimal b = fun.test("45.64");System.out.println(b);}@Testpublicvoidtest9(){Fun fun =BigDecimal::new;BigDecimal b = fun.test("45.64");System.out.println(b);}
privateList<Employee> employees =Arrays.asList(newEmployee("soo",8547.322,17),newEmployee("lili",1000D,18),newEmployee("王萌",2154D,16),newEmployee("张帆",8547.322,22),newEmployee("张帆",8547.322,22),newEmployee("张帆",8547.322,22),newEmployee("goog",353D,12));privateList<String> list =Arrays.asList("aaa","bbb","ccc","ddd","eee");
//Employee类重写equals hashCode@Overridepublicbooleanequals(Object o){if(this== o)returntrue;if(o ==null||getClass()!= o.getClass())returnfalse;Employee employee =(Employee) o;if(!Objects.equals(name, employee.name))returnfalse;if(!Objects.equals(salary, employee.salary))returnfalse;returnObjects.equals(age, employee.age);}@OverridepublicinthashCode(){int result = name !=null? name.hashCode():0; result =31* result +(salary !=null? salary.hashCode():0); result =31* result +(age !=null? age.hashCode():0);return result;}
@Testpublicvoidtest3(){boolean b = employees.stream().allMatch((e)-> e.getAge()>10);System.out.println(b); b = employees.stream().anyMatch((e)-> e.getAge()>100);System.out.println(b); b = employees.stream().noneMatch((e)-> e.getAge()>100);System.out.println(b);Optional<Employee> first = employees.stream().findFirst();System.out.println(first.get());Optional<Employee> any = employees.stream().findAny();System.out.println(any.get());long count = employees.stream().count();System.out.println(count);Optional<Employee> max = employees.stream().max(Comparator.comparingInt(Employee::getAge));System.out.println(max.get());Optional<Integer> maxAge = employees.stream().map(Employee::getAge).max(Integer::compare);System.out.println(maxAge.get());}
@Testpublicvoidtest(){List<Integer> list =Arrays.asList(1,2,3,4,5,6,7,8,9);Integer sum = list.stream().reduce(0,Integer::sum);System.out.println(sum);Optional<Double> reduce = employees.stream().map(Employee::getSalary).reduce(Double::sum);System.out.println(reduce.get());}
packagetest.time;importjava.text.SimpleDateFormat;publicclassTest1{publicstaticvoidmain(String[] args){SimpleDateFormat format =newSimpleDateFormat("yyyyMMdd");Runnable r =newRunnable(){@Overridepublicvoidrun(){try{System.out.println(format.parse("20191231"));}catch(Exception e){thrownewRuntimeException(e);}}};for(int i=0; i<100; i++){newThread(r,"t"+i).start();}}}
packagetest.time;importjava.text.SimpleDateFormat;publicclassTest1{publicstaticvoidmain(String[] args){SimpleDateFormat format =newSimpleDateFormat("yyyyMMdd");Runnable r =newRunnable(){@Overridepublicvoidrun(){synchronized(format){try{System.out.println(format.parse("20191231"));}catch(Exception e){thrownewRuntimeException(e);}}}};for(int i=0; i<100; i++){newThread(r,"t"+i).start();}}}
java.time.OffsetDateTime 带有时区偏移量的日期和时间,是LocalDateTime和ZoneOffset的结合体,更适用于需要精确到时间和偏移量的场景,尤其当你关心的只是某个时间点相对于 UTC 的偏移。例如,在处理需要表示时间差(例如时间戳、系统日志等)时,OffsetDateTime 比较合适。
publicclassTestVolatile{staticvolatileboolean flag =false;publicstaticvoidmain(String[] args){newThread(()->{try{Thread.sleep(2000);}catch(InterruptedException e){ e.printStackTrace();} flag =true;System.out.println("子线程修改flag的值为: "+ flag);}).start();// while(true) 调用底层代码,效率极高,不会从主存中再次获取被其他线程修改过的数据while(true){if(flag){System.out.println("flag is true 主线程结束循环!");break;}}}}
classMyThreadextendsThread{publicMyThread(String name){super(name);}@Overridepublicvoidrun(){System.out.println("Thread is running.");System.out.println(Thread.currentThread().getName());}}MyThread thread =newMyThread("t1");thread.start();
classMyThreadextendsThread{@Overridepublicvoidrun(){System.out.println("Thread is running.");System.out.println(Thread.currentThread().getName());}}MyThread thread =newMyThread();thread.setName("t1");thread.start();
通过匿名内部类写法
newThread("t1"){@Overridepublicvoidrun(){System.out.println("Thread is running.");System.out.println(Thread.currentThread().getName());}}.start();
publicsynchronizedvoidstart(){/** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */if(threadStatus !=0)thrownewIllegalThreadStateException();/* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */ group.add(this);boolean started =false;try{start0(); started =true;}finally{try{if(!started){ group.threadStartFailed(this);}}catch(Throwable ignore){/* do nothing. If start0 threw a Throwable then it will be passed up the call stack */}}}privatenativevoidstart0();
synchronized (lock) { while (条件不满足) { lock.wait(); } //继续执行后面操作}
例1:如果使用if,wait中的线程被唤醒时,不会再次判断if中的条件
publicclassSimpleWakeupDemo{privatevolatilestaticboolean flag =true;privatestaticfinalObject lock =newObject();publicstaticbooleancondition(){System.out.println(Thread.currentThread().getName()+"判断flag = "+ flag);return flag;}publicstaticvoidmain(String[] args){Thread t1 =newThread(){@Overridepublicvoidrun(){synchronized(lock){if(condition()){try{System.out.println(Thread.currentThread().getName()+" before wait"); lock.wait();System.out.println(Thread.currentThread().getName()+" after wait");}catch(InterruptedException e){thrownewRuntimeException(e);}}System.out.println(Thread.currentThread().getName()+"打印flag = "+ flag);}}};Thread t2 =newThread(){@Overridepublicvoidrun(){synchronized(lock){try{Thread.sleep(900); lock.notifyAll();}catch(InterruptedException e){thrownewRuntimeException(e);}}}}; t1.start(); t2.start();}}
Thread-0判断flag = trueThread-0 before waitThread-0 after waitThread-0打印flag = true
如果改成while,可以看到wait结束后,会再次判断条件是否成立
while(condition()){try{System.out.println(Thread.currentThread().getName()+" before wait"); lock.wait();System.out.println(Thread.currentThread().getName()+" after wait");}catch(InterruptedException e){thrownewRuntimeException(e);}}
Thread-0判断flag = trueThread-0 before waitThread-0 after waitThread-0判断flag = trueThread-0 before wait
publicclassTestThread{publicstaticvoidmain(String[] args){for(int i =0; i <10; i++){newMyThread("T"+i).start();}}}classMyThreadextendsThread{privatestaticInteger i =1000;//同步监视器,锁privatestaticObject object =newObject();publicMyThread(String name){super(name);}@Overridepublicvoidrun(){while(true){synchronized(object){if(i >0){ i--;System.out.println(Thread.currentThread().getName()+"->"+ i);}else{break;}}}}}
3.3 Runnable创建线程时,使用同步方法加锁
publicclassTestRunnable{publicstaticvoidmain(String[] args){Runnable runnable =newRunnable(){privateint num =1000;@Overridepublicvoidrun(){while(true){this.show();}}publicsynchronizedvoidshow(){try{Thread.sleep(20);}catch(InterruptedException e){ e.printStackTrace();}if(num >0){ num--;System.out.println(Thread.currentThread().getName()+"->"+ num);}}};for(int i =0; i <10; i++){newThread(runnable,"T"+ i).start();}}}
3.4 Thread创建线程时,使用同步方法加锁
publicclassTestThread{publicstaticvoidmain(String[] args){TicketTest ticketTest =newTicketTest();for(int i =0; i <10; i++){newThread("T"+i){@Overridepublicvoidrun(){while(true){ ticketTest.test();}}}.start();}}staticclassTicketTest{privateint num =1000;privatesynchronizedvoidtest(){if(num >0){ num--;System.out.println(Thread.currentThread().getName()+"->"+ num);}}}}