虽然好几次学习了这三个,但是过了一段时间就又忘记了,决定总结一下,有错误留言一起讨论哟
static
1、static修饰类
static是不能修饰public所修饰的类的,但是可以有静态内部类,例如:
public class TestStatic {
public static class innerClassStatic{
public innerClassStatic() {
// TODO Auto-generated constructor stub
System.out.println("静态内部类调用----");
}
public static String getNumber(){
return "2";
}
public String getNumberTwo(){
System.out.println(innerClassStatic.getNumber());
return "aa";
}
}
public void getNumberOpt(){
//静态内部类只能通过类名调用
//新建一个静态内部类对象调用非静态方法
System.out.println(new TestStatic.innerClassStatic().getNumberTwo());
System.out.println("-----------------------------------------------");
//下面方法最好不要用,尽可能只在静态方法中调用
System.out.println(new TestStatic.innerClassStatic().getNumber());
System.out.println("-----------------------------------------------");
System.out.println(TestStatic.innerClassStatic.getNumber());
System.out.println("-----------------------------------------------");
//第一句话的调用结果是:
// 2
// 静态内部类调用----
// 2
}
/**
* 静态方法
* @param args
*/
public static void main(String[] args) {
System.out.println("1-----------------------------------------------");
System.out.println(TestStatic.innerClassStatic.getNumber());
System.out.println("2-----------------------------------------------");
System.out.println(new TestStatic.innerClassStatic().getNumberTwo());
System.out.println("3-----------------------------------------------");
new TestStatic().getNumberOpt();
}
/**
* 调用结果是:
第1步-----------------------------------------------
2
第2步-----------------------------------------------
静态内部类调用----
2
aa
第3步-----------------------------------------------
静态内部类调用----
2
aa
-----------------------------------------------
静态内部类调用----
2
-----------------------------------------------
2
-----------------------------------------------
*/
}
2、static静态块与修饰变量和方法
public class TestStatic {
//不可以被外部类调用,只能通过类方法调用
private static int a=1;
public static int b=3;
static{
System.out.println("static静态块");
a++;
b++;
}
public TestStatic() {
// TODO Auto-generated constructor stub
System.out.println("构造方法");
a++;
}
public static void testN(){
System.out.println("静态方法");
a++;
b++;
}
public void testNTwo(){
System.out.println("非静态方法");
}
}
public class TestStaticTwo {
public static void main(String[] args) {
System.out.println("----第一步----");
TestStatic.testN();
System.out.println("----第二步----");
TestStatic testStatic=new TestStatic();
testStatic.testNTwo();
System.out.println("----第三步----");
System.out.println(TestStatic.b+"@@");
}
/**
* 结果:
----第一步----
static静态块
静态方法
----第二步----
构造方法
非静态方法
----第三步----
5@@
*/
}
1、可见 静态块在全过程之中,只有在加载类的时候加载一次,其他时候都不会调用了
2、static修饰的变量从始至终只有一个存储的空间,不会随着对象的改变而改变
3、static修饰的方法或者静态块中只能够访问静态的变量或者方法
final
这个我在网上看到一个比较精辟的话,就是:
修饰变量:为常量,值不能改变
修饰对象:值能够改变,而引用不能改
修饰方法:不能够重写
修饰类:不可以被继承
synchronized
1、synchronized的同步锁是this对象(当前对象)
1.1 同步方法
public class TestThread {
//synchronized的同步锁是this对象(类的对象)
//1、修饰类
public synchronized void syschronThread1(){
System.out.println("当前调用synchronThread1方法的线程是:"+Thread.currentThread().getName());
for(int i=0;i<5;i++){
System.out.println("这是syschronThread1方法执行的同步方法,"+i);
}
}
public static void main(String[] args) {
final TestThread testThread=new TestThread();
//测试1 syschronThread1
Thread t1=new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
testThread.syschronThread1();
}
},"thread1");
/*t1.setName("");*/
Thread t2=new Thread(new Runnable(){
public void run() {
// TODO Auto-generated method stub
testThread.syschronThread1();
}
},"thread2");
//使用start方法名称就对了,使用run方法名称就是main
//原因是:
//区别:调用start方法实现多线程,而调用run方法没有实现多线程
//Start:
// 用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。
// 通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到spu时间片,
// 就开始执行run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。
//Run:
// run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,
// 其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,
// 这样就没有达到写线程的目的。
//总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。
t1.start();
t2.start();
t1.run();
t2.run();
}
/**
start方法实现了多线程,程序测试的就是多线程的影响
调用结果是:
当前调用synchronThread1方法的线程是:thread1
这是syschronThread1方法执行的同步方法,0
这是syschronThread1方法执行的同步方法,1
这是syschronThread1方法执行的同步方法,2
这是syschronThread1方法执行的同步方法,3
这是syschronThread1方法执行的同步方法,4
当前调用synchronThread1方法的线程是:thread2
这是syschronThread1方法执行的同步方法,0
这是syschronThread1方法执行的同步方法,1
这是syschronThread1方法执行的同步方法,2
这是syschronThread1方法执行的同步方法,3
这是syschronThread1方法执行的同步方法,4
run方法只是一个线程,按顺序执行罢了,没有测试的必要
当前调用synchronThread1方法的线程是:main
这是syschronThread1方法执行的同步方法,0
这是syschronThread1方法执行的同步方法,1
这是syschronThread1方法执行的同步方法,2
这是syschronThread1方法执行的同步方法,3
这是syschronThread1方法执行的同步方法,4
当前调用synchronThread1方法的线程是:main
这是syschronThread1方法执行的同步方法,0
这是syschronThread1方法执行的同步方法,1
这是syschronThread1方法执行的同步方法,2
这是syschronThread1方法执行的同步方法,3
这是syschronThread1方法执行的同步方法,4
*/
}
1.2 同步块
public class TestThread {
//synchronized的同步锁是this对象(类的对象)
//2、修饰代码块
public void syschronThread2(){
synchronized(this){
System.out.println("当前调用synchronThread2方法的线程是:"+Thread.currentThread().getName());
for(int i=0;i<5;i++){
System.out.println("这是syschronThread2方法执行的同步块,"+i);
}
}
}
public static void main(String[] args) {
final TestThread testThread=new TestThread();
//测试1 syschronThread1
Thread t1=new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
testThread.syschronThread2();
}
},"thread3");
Thread t2=new Thread(new Runnable(){
public void run() {
// TODO Auto-generated method stub
testThread.syschronThread2();
}
},"thread4");
t1.start();
t2.start();
}
/**
运行结果是:
当前调用synchronThread2方法的线程是:thread3
这是syschronThread2方法执行的同步块,0
这是syschronThread2方法执行的同步块,1
这是syschronThread2方法执行的同步块,2
这是syschronThread2方法执行的同步块,3
这是syschronThread2方法执行的同步块,4
当前调用synchronThread2方法的线程是:thread4
这是syschronThread2方法执行的同步块,0
这是syschronThread2方法执行的同步块,1
这是syschronThread2方法执行的同步块,2
这是syschronThread2方法执行的同步块,3
这是syschronThread2方法执行的同步块,4
*/
}
1.3两者综合使用
public class TestThread {
//synchronized的同步锁是this对象(类的对象)
//1、修饰类
public synchronized void syschronThread1(){
System.out.println("当前调用synchronThread1方法的线程是:"+Thread.currentThread().getName());
for(int i=0;i<5;i++){
System.out.println("这是syschronThread1方法执行的同步方法,"+i);
}
}
//2、修饰代码块
public void syschronThread2(){
synchronized(this){
System.out.println("当前调用synchronThread2方法的线程是:"+Thread.currentThread().getName());
for(int i=0;i<5;i++){
System.out.println("这是syschronThread2方法执行的同步方法,"+i);
}
}
}
public static void main(String[] args) {
final TestThread testThread=new TestThread();
Thread t2=new Thread(new Runnable(){
public void run() {
// TODO Auto-generated method stub
testThread.syschronThread2();
}
},"thread2");
Thread t1=new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
testThread.syschronThread1();
}
},"thread1");
t1.start();
t2.start();
}
/**
调用结果是:
当前调用synchronThread1方法的线程是:thread1
这是syschronThread1方法执行的同步方法,0
这是syschronThread1方法执行的同步方法,1
这是syschronThread1方法执行的同步方法,2
这是syschronThread1方法执行的同步方法,3
这是syschronThread1方法执行的同步方法,4
当前调用synchronThread2方法的线程是:thread2
这是syschronThread2方法执行的同步方法,0
这是syschronThread2方法执行的同步方法,1
这是syschronThread2方法执行的同步方法,2
这是syschronThread2方法执行的同步方法,3
这是syschronThread2方法执行的同步方法,4
*/
}
得出结论是:
syschronTread1和syschronTread2都是使用的是this锁,所以当一个线程占用锁的时候,另外一个线程需要等待
2、synchronized的同步锁是类对象
public class TestThread {
//synchronized的同步锁是类对象)
//1、修饰类
public static synchronized void syschronThread1(){
System.out.println("当前调用synchronThread1方法的线程是:"+Thread.currentThread().getName());
for(int i=0;i<5;i++){
System.out.println("这是syschronThread1方法执行的同步方法,"+i);
try
{
Thread.sleep(500);
}
catch (InterruptedException ie)
{
}
}
}
//2、修饰代码块
public void syschronThread2(){
synchronized(TestThread.class){
System.out.println("当前调用synchronThread2方法的线程是:"+Thread.currentThread().getName());
for(int i=0;i<5;i++){
System.out.println("这是syschronThread2方法执行的同步方法,"+i);
try
{
Thread.sleep(500);
}
catch (InterruptedException ie)
{
}
}
}
}
public static void main(String[] args) {
Thread thread2=new Thread(new Runnable(){
public void run() {
// TODO Auto-generated method stub
new TestThread().syschronThread2();
}
},"thread2");
Thread thread1=new Thread(new Runnable(){
public void run() {
// TODO Auto-generated method stub
TestThread.syschronThread1();
}
},"thread1");
thread2.start();
thread1.start();
}
/**
* 运行结果是:
当前调用synchronThread1方法的线程是:thread1
这是syschronThread1方法执行的同步方法,0
这是syschronThread1方法执行的同步方法,1
这是syschronThread1方法执行的同步方法,2
这是syschronThread1方法执行的同步方法,3
这是syschronThread1方法执行的同步方法,4
当前调用synchronThread2方法的线程是:thread2
这是syschronThread2方法执行的同步方法,0
这是syschronThread2方法执行的同步方法,1
这是syschronThread2方法执行的同步方法,2
这是syschronThread2方法执行的同步方法,3
这是syschronThread2方法执行的同步方法,4
*/
}
小知识点:
sleep和wait的区别:
sleep(100L)是占用cpu,线程休眠100毫秒,其他进程不能再占用cpu资源,
wait(100L)是进入等待池中等待,交出cpu 等系统资源供其他进程使用,在这100毫秒中,该线程可以被其他线程notify,但不同的是其他在等待池中的线程不被notify不会出来,但这个线程 在等待100毫秒后会自动进入就绪队列等待系统分配资源,
换句话说,sleep(100)在100毫秒后肯定会运行,但wait在100毫秒后还有等待 os调用分配资源,所以wait100的停止运行时间是不确定的,但至少是100毫秒。