JAVA concurrent programming-Application
When it comes to java multithreading, some people may have a big head. Many concepts are very understandable, but they do not know how to operate it when it comes to practice. Next we will talk about the multi-threaded application based on actual projects.
Business Requirements:
Example: insert 0.1 million coupons for related activities in batches
Operation Method: Use a fixed 10-size thread pool to process 1000 inserted data records at a time.
Thread class: Note Callable implementation The interface is a thread class that can get the returned value.
Public class InsertBatchThread implements Callable
{Private int vdate; private int uid; private int count; private FundsInfoMapper fundsInfoMapper; private extends WmpsDayInterMapper; private DataSource; public wmpsDayInterMapper extends () {if (null = WmpsDayInterMapper) {synchronized (this) {if (null = wmpsDayInterMapper) {wmpsDayInterMapper = SpringContextUtils. getBean ("wmpsDayInterMapper") ;}} return wmpsDayInterMapper;} public FundsInfoMapper extends () {if (null = fundsInfoMapper) {synchronized (this) {if (null = fundsInfoMapper) {fundsInfoMapper = SpringContextUtils. getBean ("fundsInfoMapper") ;}} return fundsInfoMapper;}/*** No parameter constructor */public InsertBatchThread () {}/*** No parameter constructor */public InsertBatchThread (int vdate, int uid, int count) {this. vdate = vdate; this. uid = uid; this. count = count; this. fundsInfoMapper = getFundsInfoMapper (); this. wmpsDayInterMapper = getWmpsDayInterMapper ();}/*** a method specified by multiple threads. to inherit the Thread class, you must implement this method */public Integer call () {int result =-1; try {// operation List
ListUsers = fundsInfoMapper. selectUserForInsertBatch (count * 1000,100 0); // Insert the List of user activity coupon records in batches
ListOnePageDayInner = wmpsDayInterMapper. selectByInsertBatch (vdate, listUsers. get (0), listUsers. get (listUsers. size ()-1); wmpsDayInterInsertBatch (listOnePageDayInner);} catch (Exception e) {result = count;} return result ;} // insert a user activity coupon record table in batches -- JDBC public int [] wmpsDayInterInsertBatch (List
ListOnePage) throws Exception {dataSource = SpringContextUtils. getBean ("dataSource"); PreparedStatement ps = dataSource. getConnection (). prepareStatement ("INSERT ignore INTO t_a (uid, inter, cdate) values (?,?,?) "); For (WmpsDayInter oneObj: listOnePage) {ps. setInt (1, oneObj. getUid (); ps. setBigDecimal (2, oneObj. getInter (); ps. setBigDecimal (3, oneObj. getCdate (); ps. addBatch () ;}return ps.exe cuteBatch ();}}
Corresponding business implementation class:
/*** Coupon */@ Service ("FundsInfoService") public class FundsInfoServiceImpl extends BaseService
Implements IFundsInfoService {private final static Logger LOGGER = LoggerFactory. getLogger (FundsInfoServiceImpl. class); @ Autowired private FundsInfoMapper fundsInfoMapper; public FundsInfoServiceImpl () {}@ Override public void insertDayInter (Integer vdate, Integer uid) {// if (vdate = null | vdate. intValue () <= 0 | uid = null | uid. intValue () <0) {LOGGER. error ("= insertDayInter => error, vdate =" + vdate + ", uid =" + uid);} else {// count the qualified user int totalNum = fundsInfoMapper. countForInsertBatchByUser (); List
ListException = new ArrayList
(); // Initialize the start value of the first batch int startRow = 0; try {// fixed-size thread pool ExecutorService fixedThreadPool = Executors. newFixedThreadPool (10); for (int I = 0; I <= Math. floor (totalNum/1000); I ++) {Future
Future = fixedThreadPool. submit (new InsertBatchThread (vdate, uid, I); if (future. get ()> = 0) {listException. add (future. get () ;}// the coupon is sent out to verify whether any omission exists. if yes, the if (listException. size ()> 0) {for (int I = 0; I <= listException. size (); I ++) {Future
Future = fixedThreadPool. submit (new InsertBatchThread (vdate, uid, listException. get (I); if (future. get ()> = 0) {listException. add (future. get () ;}}} catch (Exception e) {LOGGER. error ("<= insertDayInter => error", e) ;}} LOGGER.info ("<= insertDayInter => ");}}
The problem is that when we need multi-threaded operations, we usually query the data before inserting it. However, if we do not have a reasonable dimension to split the data, it is easy to cause a deadlock. For example, if we do not properly allocate dimensions, it is possible that batch 1 and batch 2 process the same data simultaneously, both query and update, each Other can continue execution only after the lock is released, resulting in a deadlock.