javase部分完结,下个知识点:数据库
1、多线程
什么是多线程?(关键字:Thread)
一个程序叫做进程,程序能够同时做很多任务,同时运行很多任务叫做多线程。每一个任务就是一个线程。例如jvm处理源代码的时候,jvm就是一个进程,main方法和GC回收方法就是两个线程。
实现多线程的两种方法:
1、继承Thread,调用start方法,start方法是开辟了新的栈空间,新的栈空间和main方法栈是平级的:
public class Test {
public static void main(String[] args) {
MyThread t=new MyThread();
t.start();
for(int i=0;i<3;i++){
System.out.println(i+"main");//0my 0main 1main 2main 1my 2my//运行结果每次都不同,因为每次线程抢夺的时间片可能不同
}
}
}
class MyThread extends Thread{
public void run(){
for(int i=0;i<3;i++){
System.out.println(i+"my");
}
}
}
2、实现Runnable接口:
public class Test {
public static void main(String[] args) {
MyThread t=new MyThread();
Thread thread=new Thread(t);
thread.start();
for(int i=0;i<3;i++){
System.out.println(i+"main");//0my 0main 1my 1main 2my 2main
}
}
}
class MyThread implements Runnable{
public void run(){
for(int i=0;i<3;i++){
System.out.println(i+"my");
}
}
}
线程的常用方法:
1、Thread.currentThread():获取当前线程
2、Thread.currentThread().getName()、setName():获取当前线程名字、设置当前线程名字
3、Thread.sleep():使当前线程休眠,单位毫秒
4、interrupt)():打断线程的休眠
5、stop():线程的终止,已过时,不建议使用,容易丢失数据。可以采用在run()函数中加判断等于true就运行,在main方法中写入等于false的语句来终止线程。
6、setPriority(int):设置线程的优先级,优先级最高10,最低1,默认优先级是5,优先级的高低跟执行顺序没关系,跟抢夺时间片的多少有关系,一般来说,优先级高的线程先执行完。
7、getPriority():获取线程的优先级。
8、yield():将线程的时间片让位给其他线程,但是这个操作需要时间,业务逻辑需求的代码谨慎使用。
9、join():当前线程进入阻塞状态,线程对象执行,直到线程对象结束,当前线程才可以执行。
线程同步:
1、同步编程模型:线程之间有等待关系,有安全性。但是效率低。
2、异步编程模型:线程之间没有等待关系,各自执行各自的。没有安全概念。
线程安全(关键字synchronized):
如果多个线程同时访问一个数据,就会发生数据的安全问题。这个时候就要用到同步编程模型。
1、synchronized (锁定的对象){代码块},灵活
2、synchronized 出现在实例方法上,一定锁的是this,不灵活
3、synchronized出现在静态方法上,锁的是类锁,即使创建再多对象,也是一把锁。
死锁:
两个线程之间互相锁住自己的对象,谁也不解锁自己的对象。所以尽量不要使用嵌套。
public class Test {
public static void main(String[] args) throws InterruptedException {
Object obj1=new Object();
Object obj2=new Object();
MyThread1 t1=new MyThread1(obj1,obj2);
MyThread2 t2=new MyThread2(obj1,obj2);
t1.start();
t2.start();
}
}
class MyThread1 extends Thread{
Object obj1;
Object obj2;
public MyThread1(Object obj1,Object obj2){
this.obj1=obj1;
this.obj2=obj2;
}
@Override
public void run(){
synchronized (obj1){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj2){
}
}
}
}
class MyThread2 extends Thread{
Object obj1;
Object obj2;
public MyThread2(Object obj1,Object obj2){
this.obj1=obj1;
this.obj2=obj2;
}
@Override
public void run() {
synchronized (obj2){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj1){
}
}
}
}
守护线程:
守护线程是伴随着用户线程并发的,一旦用户线程结束,守护线程必须结束。例如垃圾回收机制。
Thread.setDaemon(true):将线程转换为守护线程。
定时器(关键字:schedule):
public class Test {
public static void main(String[] args) throws InterruptedException, ParseException {
Timer t=new Timer();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date first=sdf.parse("2020-07-05 13:05:00");
t.schedule(new Task(0),first,1000);//1 2 3...
}
}
class Task extends TimerTask{
int i;
public Task(int i) {
this.i = i;
}
@Override
public void run() {
if(i>=0){
i=i+1;
System.out.println(i);
}
}
}
生成者和消费者模式(关键字:wait和notify,这两个方法不是线程的方法,是java对象的方法):
生产者和消费者模式就是生产数据到一个空间中,并且同时在这个空间消费数据,这就要求生产者和消费者之间必须平衡。
public class Test {
public static void main(String[] args) {
List list=new ArrayList();
Thread t1=new Thread(new Producer(list));
Thread t2=new Thread(new Coustomer(list));
t1.setName("生产者线程");
t2.setName("消费者线程");
t1.start();
t2.start();
}
}
class Producer implements Runnable{
private List list;
public Producer(List list) {
this.list = list;
}
@Override
public void run() {
while (true){
synchronized (list){
if(list.size()>0){
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Object obj=new Object();
list.add(obj);
System.out.println(Thread.currentThread().getName()+obj);
list.notifyAll();
}
}
}
}
class Coustomer implements Runnable{
private List list;
public Coustomer(List list) {
this.list = list;
}
@Override
public void run() {
while (true){
synchronized (list){
if(list.size()==0){
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
Object obj=list.remove(0);
System.out.println(Thread.currentThread().getName()+obj);
list.notifyAll();
}
}
}
}
}
2、反射机制
什么是反射(关键字:reflect)?
通过反射可以去操作字节码文件。
获取类的字节码有三种方式:
1、Class c= Class.forName("");
2、引用对象.getClass();
3、Class c=任何类型.class
public class Test {
public static void main(String[] args) {
try {
Class c=Class.forName("Person");//class Person
System.out.println(c);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Person p=new Person();
Class c1=p.getClass();
Class c2=Person.class;
System.out.println(c1);//class Person
System.out.println(c2);//class Person
}
}
class Person{
String name;
}
类对象方法:
1、newInstance():调用类的无参构造方法。已过时,搭配Properties和IO流就可以灵活的实现类的调用。这样调用的好处是更改类只需要在properties配置文件中修改就可以。
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
Properties p=new Properties();
FileReader r=new FileReader("os.properties");
p.load(r);
String classname=p.getProperty("classname");
Class c=Class.forName(classname);
Object obj=c.newInstance();
System.out.println(obj);//Person@4f3f5b24
}
}
class Person{
String name;
}
os.properties内容
classname=Person
2、getFields():获取类中所有公开的属性,返回一个Field[]
Field方法:Field.getModifiers:获取属性的类型,返回值是int类型,可以通过Modifiers.toString()转换
3、getDeclaredFields():获取类中所有属性,返回一个Field[]
3、getMethods():获取所有公开类的方法,返回一个Method[]
Method方法:Method.getReturnType().getSimpleName():获取方法返回值类型的名称
Method.getParameterTypes().getSimpleName():获取方法参数类型的名称
4、s.getDeclaredMethods():获取类中所有方法,返回一个Method[]
5、Method.invoke(实例):根据实例配置的参数去调用方法
番外:形式参数中的…
表示参数个数是不固定的,但是只能放在参数的最后面
public class ArgsTest {
public static void main(String[] args) {
c("asda",23,324);//c
c1("asd","asd");//asd asd
}
public static void c(String v,int... args){
System.out.println("c");
}
public static void c1(String... c) {
for(int i=0;i<c.length;i++){
System.out.println(c[i]);
}
}
}
3、注解
注解:
注释的一种,是一种引用数据类型,编译生成之后也是class文件
语法:[修饰符列表] @interface 注解类型名{}
注解怎么使用?用在什么地方?
注解的语法格式是@注解类型名
注解可以出现在类上、属性上、方法上、变量上等还可以出现上注解类型上
jdk中有哪些内置的注解:@Override父类重写的方法
@Override这个注解是给编译器参考的,如果不是父类重写的方法,编译器会报错
元注解:是标注注解的注解
常见的元注解:target、Retention
target是标注的注解只能出现在什么上
Retention是标注的注解最终保存到哪里
Deprecated这个注解标注的是已过时