复习面试题中遇到锁的内容当时大一学习的时候感觉懵懂,现在重新复习一下。

1.1多线程

  1.1.1线程

    1.什么是线程

    线程是程序执行的一条路径,一个进程中包含多条进程

    2.并行与并发

    并行是两个任务同时运行,甲任务进行的同时,乙任务也在进行

    并发是指两个任务都请求运行,处理器只能处理一个任务,就将两个任务进行轮流进行

       3.Java程序运行原理和JVM的启动是否为多线程

    A:Java程序运行原理

      Java命令会启动Java虚拟机,启动JVM,等于启动了一个应用程序,也就是启动了一个进程,该进程为主线程,主线程去调用某个main方法

    B:JVM的启动是多线程的吗

      JVM的启动至少启动了垃圾回收线程和主线程,所以是多线程的

       

    证明JVM运行是多线程

package com.littlepage.test2;

public class Demo {
@Override
protected void finalize(){
System.out.println("rubbish is cleaned");
}
public static void main(String[] args) {
for(int i=;i<;i++){
new Demo();
}
for(int i=;i<;i++){
System.out.println("main is doing");
}
}
}

  1.1.1实现方式

    1.继承Thread类

public class TreadDemo01 {
public static void main(String[] args) {
MyThread mt=new MyThread();
mt.start();
for(int i=;i<;i++){
System.out.println("Main method");
}
}
} class MyThread extends Thread{
@Override
public void run() {
for(int i=;i<;i++){
System.out.println("My Thread is running");
}
}
}

    2.实现runnable接口

package com.littlepage.test2;

public class ThreadDemo02 {
public static void main(String[] args) {
MyRunnable mr=new MyRunnable();
new Thread(mr).start();
for(int i=;i<;i++){
System.out.println("Main method");
}
}
} class MyRunnable implements Runnable{
@Override
public void run() {
for(int i=;i<;i++){
System.out.println("My Runnable is running");
}
}
}

    3.何时使用继承何时使用接口

      一般情况下使用继承的多线程,因为代码简单,接口线程在一个类有了父类的时候,使用接口

    4.匿名内部类进行多线程

package com.littlepage.test2;

public class ThreadDemo03 {
public static void main(String[] args) {
new Thread(){
@Override
public void run() {
for(int i=;i<;i++){
System.out.println("My Thread is running");
}
}
}.start();
for(int i=;i<;i++){
System.out.println("Main method");
}
}
}
package com.littlepage.test2;

public class ThreadDemo03 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
for(int i=;i<;i++){
System.out.println("My Runnable is running");
}
}
}).start();
for(int i=;i<;i++){
System.out.println("Main method");
}
}
}

1.2获取线程名和设置线程名

   1.1获取线程名字(线程的默认名字为Thread-0 Thread-1....)

package com.littlepage.test2;

public class Demo04GetName {
public static void main(String[] args) {
new Thread(){
@Override
public void run() {
System.out.println(getName());
}
}.start();
new Thread(){
@Override
public void run() {
System.out.println(getName());
}
}.start();
}
}
package com.littlepage.test2;

public class Demo04GetName {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}).start();;
}
}

    1.2设置线程名

package com.littlepage.test2;

public class Demo04GetName {
public static void main(String[] args) {
Thread t1=new Thread(){
@Override
public void run() {
System.out.println(getName());
}
};
t1.setName("线程0");
Thread t2=new Thread(){
@Override
public void run() {
System.out.println(getName());
}
};
t2.setName("线程1"); t1.start();t2.start();
}
}

1.3休眠线程

   1.1简介休眠方法

    Thread.sleep(long millis) 休眠millis毫秒

    Thread.sleep(long millis,int nanosecond) 休眠millis毫秒和nanosecond纳秒

   举例:省略

1.4守护线程(Daemon)

  守护线程就是我们所说的后台程序,非守护线程结束,守护线程将会立即结束

  举例:

package com.littlepage.test2;

public class DemoDaemon {
public static void main(String[] args) {
Thread a=new Thread(){
@Override
public void run() {
for(int i=;i<;i++){
System.out.println(getName()+"\t"+i);
}
}
};
Thread b=new Thread(){
@Override
public void run() {
for(int i=;i<;i++){
System.out.println(getName()+"\t"+i);
}
}
};
a.setDaemon(true);
a.start();
b.start();
}
}

  线程2结束,守护线程1也立即结束

1.5加入线程

  加入线程join() 当前线程暂停,等待指定的线程执行结束后,再进行执行

  举例:

package com.littlepage.test2;

public class DemoDaemon {
public static void main(String[] args) {
final Thread a=new Thread(){
@Override
public void run() {
for(int i=;i<;i++){
System.out.println(getName()+"\t"+i);
}
}
};
Thread b=new Thread(){
@Override
public void run() {
for(int i=;i<;i++){
if(i==)
try {
a.join();//等a线程执行完再执行完,再执行b
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName()+"\t"+i);
}
}
};
a.setDaemon(true);
a.start();
b.start();
}
}

1.4同步代码块

  1.4.1什么情况下需要同步

    多线程并发,多段代码同时执行,我们希望某一段代码执行过程中CPU不要切换到其他线程来工作,这时候我们需要同步

    代码示例:

package com.littlepage.test2;

public class DemoSynchronized {
public static void main(String[] args) {
final Printer p=new Printer();
new Thread(){
public void run(){
while(true) p.print1();
}
}.start();
new Thread(){
public void run(){
while(true) p.print2();
}
}.start();
}
}
class Printer{
public void print1(){
System.out.print("A");
System.out.print("P");
System.out.print("P");
System.out.print("l");
System.out.println("e");
}
public void print2(){
System.out.print("B");
System.out.print("a");
System.out.print("n");
System.out.print("a");
System.out.print("n");
System.out.println("a");
}
}

  这段代码在运行过程中出现了以下情况

  

  原因是,打印过程中进行了切换导致,所以我们需要一个同步锁

package com.littlepage.test2;

public class DemoSynchronized {
public static void main(String[] args) {
final Printer p=new Printer();
new Thread(){
public void run(){
while(true) p.print1();
}
}.start();
new Thread(){
public void run(){
while(true) p.print2();
}
}.start();
}
}
class Printer{
Object lock=new Object();
public void print1(){
synchronized (lock) {
System.out.print("A");
System.out.print("P");
System.out.print("P");
System.out.print("l");
System.out.println("e");
}
}
public void print2(){
synchronized (lock) {
System.out.print("B");
System.out.print("a");
System.out.print("n");
System.out.print("a");
System.out.print("n");
System.out.println("a");
}
}
}

    锁可以是任何一个对象,这边直接new一个Object,但是在两个方法内部,必须用一个lock

1.5同步方法

package com.littlepage.test2;

public class DemoSynchronized {
public static void main(String[] args) {
final Printer p=new Printer();
new Thread(){
public void run(){
while(true) p.print1();
}
}.start();
new Thread(){
public void run(){
while(true) p.print2();
}
}.start();
}
}
class Printer{
public synchronized void print1(){
System.out.print("A");
System.out.print("P");
System.out.print("P");
System.out.print("l");
System.out.println("e");
}
public synchronized void print2(){
System.out.print("B");
System.out.print("a");
System.out.print("n");
System.out.print("a");
System.out.print("n");
System.out.println("a");
}
}

    同步方法的锁是this, 所以我们有个想法, 包括同步代码块和同步代码,我们所有的锁都可以用this关键字, 不用Object造成冗余

    静态方法的锁是字节码对象

1.6线程的安全问题

  1.6.1书本的售票例子

package com.littlepage.test2;

public class DemoTicket {
public static void main(String[] args) {
new TicketSeller("窗口1").start();
new TicketSeller("窗口2").start();
new TicketSeller("窗口3").start();
new TicketSeller("窗口4").start();
}
}
class TicketSeller extends Thread{
private static int tickets=; public TicketSeller(String windowName) {
super(windowName);
} public void run(){
while(true){
if(tickets<=){
break;
}
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName()+"......"+tickets--);
}
}
}

  结果出现了重复票和负票

    

  解决方式,加上同步代码块

package com.littlepage.test2;

public class DemoTicket {
public static void main(String[] args) {
new TicketSeller("窗口1").start();
new TicketSeller("窗口2").start();
new TicketSeller("窗口3").start();
new TicketSeller("窗口4").start();
}
}
class TicketSeller extends Thread{
private static int tickets=; public TicketSeller(String windowName) {
super(windowName);
} public void run(){
synchronized (TicketSeller.class) {
while(true){
if(tickets<=){
break;
}
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName()+"......"+tickets--);
}
}
}
}

  使用Runnable实现

1.7死锁

  

最新文章

  1. ahk之路:利用ahk在window7下实现窗口置顶
  2. C# 文件类型
  3. iOS 热点、通话时候TabView的Frame调整
  4. 千万别把js的正则表达式方法和字符串方法搞混淆了
  5. [Tutorial] Using the RasPi as a WiFi hostspot
  6. 关于 javascript:void(0) 的使用
  7. Class.forName()数据库驱动
  8. GoogleCode新手教程
  9. 创建简单的npm脚手架
  10. 深入了解UML类图
  11. 访问权限,public private protected
  12. 用VsCode写Markdown
  13. Freemarker导出带图片的word
  14. tomcat热部署.class
  15. HTTPS原理简述
  16. 记一款bug管理系统(bugdone.cn)的开发过程(1) -- 为什么要开发一款bug开发系统
  17. 南阳ACM8-一种排序
  18. 如果从excel表中导出insert-sql
  19. 总结开发ERP软件应遵循的一些基本原则
  20. Perl学习笔记(3)----遍历哈希表的一个容易疏忽的地方

热门文章

  1. Changing Ethernet Media Speed for AIX
  2. Gym 101194H / UVALive 7904 - Great Cells - [数学题+快速幂][2016 EC-Final Problem H]
  3. [摘录] 图灵机与lambda演算的关系
  4. μCOS-II移植 - 基于CortexM3
  5. RoboWare Studio 安装
  6. Oracle 数据库逻辑结构.md
  7. Golang--匿名变量
  8. 【Common】NO.81.Note.1.Common.1.002-【文章摘要】
  9. char 类型的操作函数
  10. redis安装及错误排查