创建线程的三种方法:
1:在类中继承Thread类,并重写run方法
2:new一个Thread对象,然后再实现Runnable接口,重写一个匿名内部类run;这个方法没有返回值
3: new一个FutureTask类,并在其中实现Callobel接口,重写call方法
public static void method6() {
Dog dog = new Dog();//new 一个类
FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {//new一个futureTask对象,在其中实现Callable接口,重写接口中的call方法
@Override
public Integer call() throws Exception {
Integer i=0;
for(;i<100;i++){
System.out.println(Thread.currentThread().getName()+"循环了第"+i+"遍");
}
return i;
}
});//FutureTask是一个Runnable,可以放进Tread中
//放进去就表示Tread线程中运行着FutureTask的对象中重写的方法
Thread thread = new Thread(futureTask);
thread.start();
Integer a = null;
try {
a = futureTask.get();//这是一个阻塞方法,等线程任务执行完成才会返回值,
//当get方法执行完后才会执行之后的代码;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println(a);
Thread thread2;
thread2 = new Thread(new Runnable() {//用来和thread进行对比的线程,
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始运行");
}
});
thread2.start();
}
Thread类中常用的方法
1、currentThread :获得当前Thread类对象;可以直接将此方法看作类对象,该方法后面可以直接跟其他方法,比如currentThread.getName();就可以获得当前Thread类对象的对象名;
2、join:跟在Thread对象名后面,如thread.join ,代表当前线程必须等待thread线程执行完毕后才能继续执行;
public static void method7(){
Thread thread1=new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<20;i++){
System.out.println("方法一:"+i);
}
}
});
Thread thread2=new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<20;i++){
System.out.println("方法二:"+i);
try {
thread1.join();//此方法表示让thread先执行完;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread1.start();
thread2.start();
}
多线程安全问题
java的每个线程都有自己的工作空间,线程的工作内存是互不干扰的,是相互独立的,县城内不的方法中出现的局部变量都在工作内存中存储,但线程都可以访问主存(共享内存)的空间
当多个线程同时访问共享内存的数据时才会设计到数据安全问题
解决方法
关键字:synchronized
synchronized可以加在方法声明处:
表示当前线程想要去执行这个方法必须获得当前对象的对象锁,当方法执行完后会自动释放对象锁,或者当方法遇到错误时也会自动释放对象锁,在遇到错误之前的代码会正常执行和存储值;
synchronized也可以加在方法体内部:
当synchronized加在方法体内部时,只能锁住同步代码块内部的代码,在同步代码块内部的代码执行完毕后会立刻释放对象锁
使用synchronized的注意点
如果synchronized写在了静态方法中,需要获得类对象的对象锁
下面的代码method7是将synchronized关键字写在了静态方法内部,
method8是将synchronized关键字写在了静态方法声明处,
public static void method7(){
synchronized(Dog.class){
System.out.println("运行了Dog类中的静态方法");
}
}
public synchronized static void method6(){
System.out.println("运行了Dog类中的静态方法");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}