preface

One of the most common things in Android is thread manipulation. Recently I was debugging the receipt printing machine and I started a thread that was ready to print the receipt at any time. There was a bug that I couldn’t control the number of times the receipt was printed and the order in which the thread was executed

After wandering around for a few days, I came across the Java keyword Volatile in my research

Volatile features

When a variable is volatile, it has two properties: 1. This ensures that the variable is visible to all threads. This “visibility”, as described at the beginning of this article, ensures that when a thread changes the value of the variable, the new value is immediately synchronized to main memory and flushed from main memory immediately before each use. This is not the case with ordinary variables, whose values are passed between threads through main memory (see The Java Memory Model).

2. Disable instruction reordering optimization. For volatile variables, the “load addL $0x0, (%esp)” operation is performed after the assignment. This operation acts as a memory barrier, which is not required when only one CPU accesses memory. Instruction reordering: the CPU adopts a system that allows multiple instructions to be distributed to each circuit unit in an unprogrammed order.

Volatile performance: Volatile has almost the same read performance cost as normal variables, but writes are slower because it requires inserting many memory-barrier instructions into native code to keep the processor from executing out of order.

Piece of code

First we give a volatile modifier Boolean when we initialize the variable

volatile boolean printFlag = false;
Copy the code

We set the variable printFlag to true in the thread where we get the printed data

if (bean ! = null && bean.size() > 0) { mOrderDetailBeans = bean; PrintFlag = true; }Copy the code

Then we open a thread to wirelessly wait for the data and print the receipt when we get it

new Thread(() -> { Looper.prepare(); try { while (true) { if (mUsbDriver ! While (printFlag) {ShowPrintClick(); Log.e(TAG, "=== >>> > Execute print data "); } } catch (Exception e) { Message message = new Message(); message.what = 4; message.obj = e.getMessage(); mMyHandler.sendMessage(message); } } else { Thread.sleep(1000); } } } catch (Exception e) { e.printStackTrace(); } Looper.loop(); }).start();Copy the code

ShowPrintClick method code

try { Message message = Message.obtain(); message.what = 4; Message. obj = "Geeky multifunctional drug dispensary "; mMyHandler.sendMessage(message); if (printFlag && mOrderDetailBeans.size() > 0) { mUsbDriver.write(PrintCmd.SetReadZKmode(0)); mUsbDriver.write(PrintCmd.PrintFeedDot(30)); StringBuffer header = new StringBuffer(); Header. append(" xindendy.com "+ lineEnd); Header. append(" buy medicine buy rest assured assured to xindendu medicine "+ lineEnd); header.append("------------------------------------------------" + lineEnd); header.append(lineEnd); Header. append(" Purchase date: "+ getNowDate() + lineEnd); Header. append(" order number: "+ ordersNum); mUsbDriver.write(PrintCmd.PrintString(header.toString(), 0)); OrderDetailBean orderDetailBean; StringBuffer body = new StringBuffer(); int totalNum = 0; double totalPrice = 0; for (int i = 0; i < mOrderDetailBeans.size(); i++) { orderDetailBean = mOrderDetailBeans.get(i); body.append(lineEnd); Body. The append (" drug name: "+ ((" "). The equals (orderDetailBean. GetGoodsName ())? "" : orderDetailBean.getGoodsName()) + lineEnd); Body. The append (" manufacturer: "+ ((" "). The equals (orderDetailBean. GetManufacturer ())? "" : orderDetailBean.getManufacturer()) + lineEnd); Body.append (" Spec: "+ (("").equals(OrderDetailBean.getSpec ()))? "" : orderDetailBean.getSpec()) + lineEnd); Body. The append (batch number: "" + ((" "). The equals (orderDetailBean. GetBatchNum ())? "" : orderDetailBean.getBatchNum()) + lineEnd); Body. The append (" the period of validity: "+ ((" "). The equals (orderDetailBean. GetExpireDateTime ())? "" : orderDetailBean.getExpireDateTime()) + lineEnd); Body. Append (" : "+ orderDetailBean. GetQuantity + lineEnd ()); Body. Append (" compensation: "+ orderDetailBean. GetAmount ()); body.append(lineEnd); / / here is the calculation of total commodity purchase several totalNum + = orderDetailBean. GetQuantity (); . / / accumulative total consumption totalPrice = CalcUtils addDouble (totalPrice, orderDetailBean getAmount ()); } mUsbDriver.write(PrintCmd.PrintString(body.toString(), 0)); StringBuffer total = new StringBuffer(); Total.append (" totalNum: "+ totalNum + lineEnd); Total.append (" totalPrice: "+ totalPrice + lineEnd); mUsbDriver.write(PrintCmd.PrintString(total.toString(), 0)); body.append(lineEnd); StringBuffer address = new StringBuffer(); address.append("------------------------------------------------" + lineEnd); Address.append (" this invoice is to be printed as a heavy, no basis for invoking "+ lineEnd); Address. Append (" Address: no. 1-2, 3#", 2 Shiping Qiao Zhengjie, Jiulongpo District, Chongqing, China); Address. append(" tel: 023-72223575" + lineEnd); Address.append (" Drugs are special goods and are not refundable once sold "); mUsbDriver.write(PrintCmd.PrintString(address.toString(), 0)); mUsbDriver.write(PrintCmd.PrintFeedline(5)); mUsbDriver.write(PrintCmd.PrintCutpaper(1)); PrintFlag = false; printFlag = false; } } catch (Exception e) { Message message = Message.obtain(); message.what = 4; message.obj = e.getMessage(); mMyHandler.sendMessage(message); }Copy the code

conclusion

Review the old and learn the new, can be a teacher! Ha ha ha ~